简体   繁体   English

带有平台分支的 Flutter 小部件测试

[英]Flutter widget tests with platform branching

In my widget's code I need to branch on Android/iOS to show widgets specific to each platform, and also call platform specific APIs (eg the Android widget will call an API only available on Android).在我的小部件代码中,我需要在 Android/iOS 上进行分支以显示特定于每个平台的小部件,并调用特定于平台的 API(例如,Android 小部件将调用仅在 Android 上可用的 API)。

  if (Platform.isAndroid) {
    return WidgetAndroid(...);
  } else if (Platform.isIOS) {
    return WidgetIOS(...);
  }

How can I test that the right widget is shown using a Flutter widget test?如何使用 Flutter 小部件测试来测试是否显示了正确的小部件?

I know I can check that the widget exists but how do I run the test with a specific platform.我知道我可以检查小部件是否存在,但是如何使用特定平台运行测试。

expect(find.byType(WidgetIOS), findsOneWidget);

Both Platform.isAndroid and Platform.isIOS return false when running testWidgets .运行testWidgetsPlatform.isAndroidPlatform.isIOS都返回false

Some suggestions we can apply in our tests:我们可以在测试中应用一些建议:

  • Pass the platform as variable to your top level Widget, that way you will be able to provide that value manually.将平台作为变量传递给您的顶级小部件,这样您就可以手动提供该值。
  • Make the case you want to test an else without if , so that will run during the tests.使您想在没有if的情况下测试else的情况,以便在测试期间运行。
  • Use instead Platform from https://pub.dev/packages/platform which allows mocking, which is probably the best long term solution.改用来自https://pub.dev/packages/platformPlatform ,它允许模拟,这可能是最好的长期解决方案。

Like Miguel mentioned you can't mock it directly.就像 Miguel 提到的那样,您不能直接模拟它。

If you use the provider framework, you can use dependency injection in your tests to make this happen without exposing an additional param in your widget.如果您使用提供者框架,您可以在测试中使用依赖注入来实现这一点,而无需在小部件中暴露额外的参数。

Create an class to use for injection:创建一个用于注入的类:

class PlatformInfo {
  final bool isIos;
  final bool isAndroid;

  PlatformInfo({@required this.isAndroid,@required  this.isIos});
}

in your top level MultiProvider widget, set up your provider bindings:在您的顶级MultiProvider小部件中,设置您的提供程序绑定:

Provider<PlatformInfo>.value(
    value: PlatformInfo(isAndroid: Platform.isAndroid, isIos: Platform.isIOS),
),

Use it in your widget:在您的小部件中使用它:

Provider.of<PlatformInfo>(context).isIos

Platform is in dart:io , which is lower-level than Flutter's TargetPlatform . Platform位于dart:io中,比 Flutter 的TargetPlatform低级。 In most cases, you should use the latter.在大多数情况下,您应该使用后者。

From documentation :文档

The [dart:io.Platform] object should only be used directly when it's critical to actually know the current platform, without any overrides possible (for example, when a system API is about to be called). [dart:io.Platform] 对象应该只在实际了解当前平台至关重要时直接使用,而不能进行任何覆盖(例如,当即将调用系统 API 时)。

In 2022 it is not recommended to use dart:io and Platform class to determine the runtime platform.在 2022 年不建议使用dart:ioPlatform类来确定运行时平台。 The better alternative is to use defaultTargetPlatform available through 'package:flutter/foundation.dart'.更好的选择是使用通过 'package:flutter/foundation.dart' 提供的defaultTargetPlatform Ie: IE:

if (defaultTargetPlatform == TargetPlatform.android ||
            defaultTargetPlatform == TargetPlatform.iOS) {}

Should you have that approach for determining platform in your code overiding platform in tests is as easy as setting debugDefaultTargetPlatformOverride in your test body.如果您有这种方法来确定测试中代码覆盖平台的平台,就像在测试主体中设置debugDefaultTargetPlatformOverride一样简单。

https://api.flutter.dev/flutter/foundation/debugDefaultTargetPlatformOverride.html https://api.flutter.dev/flutter/foundation/debugDefaultTargetPlatformOverride.html

Eg:例如:

  testWidgets('DataTable2 renders with DataRow.index()',
      (WidgetTester tester) async {
    debugDefaultTargetPlatformOverride = TargetPlatform.android;
 ...
    debugDefaultTargetPlatformOverride = null;
  });

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM