如何在 Flutter 中存根目标平台

Posted

技术标签:

【中文标题】如何在 Flutter 中存根目标平台【英文标题】:How to stub target platform in Flutter 【发布时间】:2019-12-28 21:23:22 【问题描述】:

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

如果平台是 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 是静态的,所以我不能对它们进行存根。

关于如何实现这一点的任何想法?

【问题讨论】:

【参考方案1】:

tl;博士

使用Theme 确认目标平台:

@override
Widget build(BuildContext context) 
  final platform = Theme.of(context).platform;

  if (platform == TargetPlatform.iOS) 
    return buildCupertinoButton();
  else 
    ...

通过设置debugDefaultTargetPlatformOverride来存根目标平台:

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 的情况。

存根目标平台

要存根目标平台,您必须设置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() 内部发生的绑定过程中,BindingBase.initServiceExtensions() 方法根据操作系统确定debugDefaultTargetPlatformOverride 的值。如果操作系统不是移动的(Android、iOS 或 Fuchsia),null 会被归属。

在测试结束时,testWidgets() 调用函数debugAssertAllFoundationVarsUnset() 检查debugDefaultTargetPlatformOverride 是否为null,以确保您没有忘记将其重置为默认值。必须这样做,因为debugDefaultTargetPlatformOverride 是一个在测试中持续存在的***变量。

重要提示:您可能很想将debugDefaultTargetPlatformOverride = null 移动到tearDown(),但由于debugAssertAllFoundationVarsUnset()tearDown() 之前被调用,它不会起作用。

【讨论】:

以上是关于如何在 Flutter 中存根目标平台的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Flutter 集成测试中最好地存根/模拟 rest API 调用

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

如何在 UITesting 上存根网络请求

如何在 GDB 中使用跟踪

如何导入依赖于 Flutter 平台的 Dart 文件或包?

如何解决flutter中的iOS部署目标问题