假设我有一个根据平台表现不同的小部件:
- 如果平台是 Android,它会显示一个
RaisedButton
。 - 如果平台是 iOS,它会显示一个
CupertinoButton
。
例子:
@override
Widget build(BuildContext context) {
if (Platform.isAndroid)
return buildRaisedButton();
else if (Platform.isIOS)
return buildCupertinoButton();
else
throw UnsupportedError('Only Android and iOS are supported.');
}
在我的widget tests ,我希望能够测试这两种情况,但由于 Platform
的 getter 是静态的,我无法对它们进行 stub 。
关于如何实现这一点有什么想法吗?
最佳答案
tl;dr
使用主题
确认目标平台:
@override
Widget build(BuildContext context) {
final platform = Theme.of(context).platform;
if (platform == TargetPlatform.iOS)
return buildCupertinoButton();
else
...
}
通过设置 debugDefaultTargetPlatformOverride
stub 目标平台:
testWidgets('`CupertinoButton` is shown in iOS.', (tester) async {
debugDefaultTargetPlatformOverride = TargetPlatform.iOS;
// run your tests
debugDefaultTargetPlatformOverride = null;
});
确认目标平台
为了使您的代码更易于测试,目标平台应该从Theme
中得到确认,而不是从Platform
中得到确认:
@override
Widget build(BuildContext context) {
final platform = Theme.of(context).platform;
if (platform == TargetPlatform.android)
return buildRaisedButton();
else if (platform == TargetPlatform.iOS)
return buildCupertinoButton();
else
throw UnsupportedError('Only Android and iOS are supported.');
}
getter defaultTargetPlatform
应该能够涵盖您无权访问 BuildContext
的情况。
stub 目标平台
要 stub 目标平台,您必须设置 debugDefaultTargetPlatformOverride
。默认情况下,Android 是小部件测试的目标平台。
例子:
testWidgets('`CupertinoButton` is shown in iOS.', (tester) async {
debugDefaultTargetPlatformOverride = TargetPlatform.iOS;
await tester.pumpWidget(MyWidget());
expect(find.byType(RaisedButton), findsNothing);
expect(find.byType(CupertinoButton), findsOneWidget);
debugDefaultTargetPlatformOverride = null;
});
注意最后一行:debugDefaultTargetPlatformOverride = null
。
这是必要的,因为在函数 testWidgets()
内部发生的绑定(bind)过程中,方法 BindingBase.initServiceExtensions()
确定——基于操作系统—— debugDefaultTargetPlatformOverride
的值。如果操作系统不是移动操作系统(Android、iOS 或 Fuchsia),则 null
被赋予属性。
在测试结束时,testWidgets()
调用函数 debugAssertAllFoundationVarsUnset()
检查 debugDefaultTargetPlatformOverride
是否为 null
以确保您没有忘记将其重置为默认值。必须这样做,因为 debugDefaultTargetPlatformOverride
是一个在测试中持续存在的顶级变量。
重要:您可能想将 debugDefaultTargetPlatformOverride = null
移动到 tearDown()
,但它不会工作,因为 debugAssertAllFoundationVarsUnset()
在 tearDown()
之前调用。
关于flutter - 如何在 Flutter 中 stub 目标平台,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57628195/