flutter - 如何在 Flutter 中 stub 目标平台

标签 flutter dart flutter-test

假设我有一个根据平台表现不同的小部件:

  • 如果平台是 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/

相关文章:

dart - 如何在 flutter 集成测试中模拟 http 请求?

json - 黑客新闻中的flutter小部件测试中, 'int'类型不是 'String'类型的子类型

flutter : How to automatically change the page after passing a certain time?

flutter - 在 Flutter 中解析复杂的 JSON

dart - 如何在Flutter中实现多个本地通知?

dart - 角 Dart : ng-repeat filter update

debugging - 如何在Android和iOS上同时运行或调试flutter项目?

sqlite - Flutter解码一列SQLite查询结果

flutter/Dart : get_cli add more controller to a page

angularjs - 可能不使用信息架构(IA)的Angular(Dart)Web应用程序路线设计指南