测试使用插件和平台通道的 Flutter 代码
Testing Flutter code that uses a plugin and platform channel
我有一个 flutter 插件,它使用平台通道来做一些本地工作。
如何为需要此插件的应用程序正确编写测试?
仅单元测试适用于纯 dart 函数。我不相信 Widget 测试能够测试使用平台通道到本地的东西。这样就剩下集成测试了。
据我了解,集成测试将启动您的主应用程序,您可以围绕您的应用程序控制它并进行测试。
对于我的情况,我只想测试使用插件的代码(使用原生内容的平台通道)。
同样重要的是从平台通道返回的值,因此使用真实的平台通道而不是模拟通道调用本机端很重要。
这可能吗?我可以告诉集成测试器打开我的应用程序的虚拟版本,有点像集成小部件测试器吗?
您的问题的简短答案似乎是否定的。 Flutter 驱动程序(集成测试)只能与 UI、AFAIK 交互。它无法拦截对插件的调用。它用于从 UI.
测试整个应用程序
但是,可以在单元和小部件测试中拦截对插件的调用。这允许监视对插件的调用并模拟响应。这样你就可以测试你的插件的飞镖代码 and/or 一个使用插件的小部件。测试本机代码将涉及编写本机测试。
以下是拦截插件调用测试的例子:
MethodChannel('audio_recorder')
.setMockMethodCallHandler((MethodCall methodCall) async {
log.add(methodCall);
switch (methodCall.method) {
case 'start':
isRecording = true;
return null;
case 'stop':
isRecording = false;
return {
'duration': duration,
'path': path,
'audioOutputFormat': extension,
};
case 'isRecording':
return isRecording;
case 'hasPermissions':
return true;
default:
return null;
}
});
有关完整示例,请参阅 here
Flutter 团队 mentions 他们想在小部件测试而不是驱动程序(集成)测试中做更多的事情。
We're moving away from flutter_driver in favour of extending flutter_test to work on devices.
来自 Flutter 2.8 的重大更改 doc, you should use binding
in tester
而不是来自频道的 setMockMethodCallHandler
。
// old code
myMethodChannel.setMockMethodCallHandler(...);
myMethodChannel.checkMockMethodCallHandler(...);
// new code
tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(myMethodChannel, ...);
tester.binding.defaultBinaryMessenger.checkMockMessageHandler(myMethodChannel, ...);
以ImagePicker为例:
widgetTest('', (tester) async {
const channel = MethodChannel('plugins.flutter.io/image_picker');
tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(
channel,
(MethodCall methodCall) => Future.value('some-image'),
);
});
@吕学洲回答的另外一件事.. 如果您正在编写单元测试并且没有对小部件测试器实例的引用,您可以访问下面的活页夹
TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger
还要确保在测试开始时等待 binder 初始化,如下所示
TestWidgetsFlutterBinding.ensureInitialized();
要获取方法调用,您可以这样做:
final binaryBinding = TestDefaultBinaryMessengerBinding.instance;
pluginChannel = MethodChannel('channelName');
binaryBinding!.defaultBinaryMessenger.setMockMethodCallHandler(pluginChannel,
(MethodCall methodCall) async {
switch (methodCall.method) {
case 'call 1':
return mockValue;
default:
return null;
}
},
);
希望对您有所帮助。
我有一个 flutter 插件,它使用平台通道来做一些本地工作。
如何为需要此插件的应用程序正确编写测试?
仅单元测试适用于纯 dart 函数。我不相信 Widget 测试能够测试使用平台通道到本地的东西。这样就剩下集成测试了。
据我了解,集成测试将启动您的主应用程序,您可以围绕您的应用程序控制它并进行测试。
对于我的情况,我只想测试使用插件的代码(使用原生内容的平台通道)。
同样重要的是从平台通道返回的值,因此使用真实的平台通道而不是模拟通道调用本机端很重要。
这可能吗?我可以告诉集成测试器打开我的应用程序的虚拟版本,有点像集成小部件测试器吗?
您的问题的简短答案似乎是否定的。 Flutter 驱动程序(集成测试)只能与 UI、AFAIK 交互。它无法拦截对插件的调用。它用于从 UI.
测试整个应用程序但是,可以在单元和小部件测试中拦截对插件的调用。这允许监视对插件的调用并模拟响应。这样你就可以测试你的插件的飞镖代码 and/or 一个使用插件的小部件。测试本机代码将涉及编写本机测试。
以下是拦截插件调用测试的例子:
MethodChannel('audio_recorder')
.setMockMethodCallHandler((MethodCall methodCall) async {
log.add(methodCall);
switch (methodCall.method) {
case 'start':
isRecording = true;
return null;
case 'stop':
isRecording = false;
return {
'duration': duration,
'path': path,
'audioOutputFormat': extension,
};
case 'isRecording':
return isRecording;
case 'hasPermissions':
return true;
default:
return null;
}
});
有关完整示例,请参阅 here
Flutter 团队 mentions 他们想在小部件测试而不是驱动程序(集成)测试中做更多的事情。
We're moving away from flutter_driver in favour of extending flutter_test to work on devices.
来自 Flutter 2.8 的重大更改 doc, you should use binding
in tester
而不是来自频道的 setMockMethodCallHandler
。
// old code
myMethodChannel.setMockMethodCallHandler(...);
myMethodChannel.checkMockMethodCallHandler(...);
// new code
tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(myMethodChannel, ...);
tester.binding.defaultBinaryMessenger.checkMockMessageHandler(myMethodChannel, ...);
以ImagePicker为例:
widgetTest('', (tester) async {
const channel = MethodChannel('plugins.flutter.io/image_picker');
tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(
channel,
(MethodCall methodCall) => Future.value('some-image'),
);
});
@吕学洲回答的另外一件事.. 如果您正在编写单元测试并且没有对小部件测试器实例的引用,您可以访问下面的活页夹
TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger
还要确保在测试开始时等待 binder 初始化,如下所示
TestWidgetsFlutterBinding.ensureInitialized();
要获取方法调用,您可以这样做:
final binaryBinding = TestDefaultBinaryMessengerBinding.instance;
pluginChannel = MethodChannel('channelName');
binaryBinding!.defaultBinaryMessenger.setMockMethodCallHandler(pluginChannel,
(MethodCall methodCall) async {
switch (methodCall.method) {
case 'call 1':
return mockValue;
default:
return null;
}
},
);
希望对您有所帮助。