S.D.
S.D.

Reputation: 5867

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 (e.g. the Android widget will call an API only available on Android).

  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?

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);

Upvotes: 17

Views: 9923

Answers (5)

Sanjay Bharwani
Sanjay Bharwani

Reputation: 4839

It can be mocked if we are using TargetPlatform instead of Platform API.

Below is the code and its test, although its unit test for a function but this works for Widget tests too.

String platformName() {
final isIOS = defaultTargetPlatform == TargetPlatform.iOS;
final isAndroid = defaultTargetPlatform == TargetPlatform.android;
if (isIOS) { return "apple";}
if (isAndroid) {return "android";}
}

Unit Test

test('test platformName for given platform', () {
final platformUtils = PlatFormUtil();
debugDefaultTargetPlatformOverride = TargetPlatform.android;
expect(platformUtils.platformName(), 'android');
debugDefaultTargetPlatformOverride = TargetPlatform.iOS;
expect(platformUtils.platformName(), 'apple');
// dont forget to reset it to avoid side effect on other tests
debugDefaultTargetPlatformOverride = null;
});

Please refer https://api.flutter.dev/flutter/foundation/TargetPlatform.html

Upvotes: 1

Maxim Saplin
Maxim Saplin

Reputation: 4672

In 2022 it is not recommended to use dart:io and Platform class to determine the runtime platform. The better alternative is to use defaultTargetPlatform available through 'package:flutter/foundation.dart'. I.e.:

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.

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

E.g.:

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

Upvotes: 33

Pierre
Pierre

Reputation: 359

Platform is in dart:io, which is lower-level than Flutter's 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).

Upvotes: 4

E. Sun
E. Sun

Reputation: 1364

Like Miguel mentioned you can't mock it directly.

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:

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

Use it in your widget:

Provider.of<PlatformInfo>(context).isIos

Upvotes: 0

Miguel Beltran
Miguel Beltran

Reputation: 2212

Both Platform.isAndroid and Platform.isIOS return false when running testWidgets.

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.
  • Use instead Platform from https://pub.dev/packages/platform which allows mocking, which is probably the best long term solution.

Upvotes: 11

Related Questions