如何在小部件测试期间存根不属于类的函数?

Posted

技术标签:

【中文标题】如何在小部件测试期间存根不属于类的函数?【英文标题】:How do I stub a function that does not belong to a class, during a widget test? 【发布时间】:2019-12-26 04:47:07 【问题描述】:

我正在使用官方的flutter相机包(https://pub.dev/packages/camera)创建一个使用原生相机拍照的flutter应用。该应用程序会打开一个模式,该模式会根据包中的availableCameras 函数的结果加载CameraPreview,而FloatingActionButton 在按下时会拍照。在为此模式创建小部件测试时,我不知道如何存根 availableCameras 函数以在测试期间返回我想要的内容。

我尝试使用 Mockito 测试包,但这仅支持模拟类。由于这个函数不属于一个类,我不能模拟它。

availableCameras 函数返回设备拥有的摄像头列表。我希望能够控制从这个函数返回的内容,以便我可以测试我的小部件对不同相机的反应。在小部件测试期间让此函数返回我想要的内容的正确方法是什么?

【问题讨论】:

【参考方案1】:

Mockito 也可以模拟函数。在 dart 中,函数是具有call 方法的类。

因此,您可以像往常一样使用 Mockito,使用抽象的 call 方法:

class MockFunction extends Mock 
  int call(String param);

这个例子代表int Function(String param)

这意味着你可以这样做:

final int Function(String) myFn = MockFunction();
when(myFn('hello world')).thenReturn(42);

expect(myFn('hello world'), equals(42));

【讨论】:

非常有趣,但不是只有在函数被注入(例如作为参数)时才有效吗?您能否提供一个模拟***函数的示例? @HugoPassos 是的,您需要一个方法来用另一个函数替换该函数。不过,有很多不同的方法可以做到这一点。例如,该函数可以是一个可变的全局变量。 有整本书专门介绍这些模式,所以我不能在这里合理地给出明确的解决方案。 是的,但我们说的是公共图书馆。在这种情况下,我无法以任何方式替换该功能。 您不必直接使用该功能。全局 var getCameras = availableCameras 应该可以解决问题。然后你的测试可以用不同的值替换它。【参考方案2】:

在这种非常特殊的情况下,您可以mock the method channel call handler。

const cameraMethodChannel = MethodChannel('plugins.flutter.io/camera');

setUpAll(() 
  cameraMethodChannel.setMockMethodCallHandler(cameraCallHandler);
);

tearDownAll(() 
  cameraMethodChannel.setMockMethodCallHandler(null);
);

Future<dynamic> cameraCallHandler(MethodCall methodCall) async 
  if (methodCall.method == 'availableCameras') return yourListOfCameras;

【讨论】:

以上是关于如何在小部件测试期间存根不属于类的函数?的主要内容,如果未能解决你的问题,请参考以下文章

Flutter:在小部件测试中测试异常

在小部件构建期间如何在颤动中导航?

如何在小部件测试中测试特定的 ProviderNotFoundException

如何在小部件测试中找到屏幕外的 ListView 子项?

Flutter - 如何在小部件测试中选择 DropdownButton 项

使用 QOpenGLContext 在小部件中进行渲染