17

I have a flutter plugin which uses the platform channel to do some native work.

How do I properly write tests for my application that requires this plugin?

Unit tests only are good for pure dart functions. I don't believe Widget testing will be able to test things that use the platform channel to native. So that leaves integration testing.

From what I understand is that integration testing will start your main application and you can control it around your app and test things.

For my case, I want to test just the code that uses the plugin (that uses the platform channel for native stuff).

Also what is important is the values that come back from the platform channel, so it is important to call the native side using a real platform channel and not a mock one.

Is that possible? Can I tell the integration tester to open a dummy version of my application, kind of like an integrated widget tester?

3 Answers 3

17

It seems the short answer to your question is no. Flutter driver (integration testing) can only interact with the UI, AFAIK. It cannot intercept calls to plugins. It is used to test the entire app from the UI.

However it is possible to intercept calls to plugins in unit and widget tests. This allows monitoring the calls to the plugin and mocking the response. That way you can test your plugin's dart code and/or a widget that uses the plugin. Testing native code would involve writing native tests.

The following is an example of intercepting calls to a plugin for testing:

MethodChannel('audio_recorder')
    .setMockMethodCallHandler((MethodCall methodCall) async {
  log.add(methodCall);
  switch (methodCall.method) {
    case 'start':
      isRecording = true;
      return null;
    case 'stop':
      isRecording = false;
      return {
        'duration': duration,
        'path': path,
        'audioOutputFormat': extension,
      };
    case 'isRecording':
      return isRecording;
    case 'hasPermissions':
      return true;
    default:
      return null;
  }
});

For a complete example see here

Sign up to request clarification or add additional context in comments.

Comments

3

Flutter team do mentions that they want to do more things in widgets test instead of driver(integration) test.

We're moving away from flutter_driver in favour of extending flutter_test to work on devices.

From Flutter 2.8 breaking changes doc, you should use binding in tester instead of setMockMethodCallHandler from channel.

// old code
myMethodChannel.setMockMethodCallHandler(...);
myMethodChannel.checkMockMethodCallHandler(...);
// new code
tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(myMethodChannel, ...);
tester.binding.defaultBinaryMessenger.checkMockMessageHandler(myMethodChannel, ...);

Take ImagePicker as example:

widgetTest('', (tester) async {
  const channel = MethodChannel('plugins.flutter.io/image_picker');
  tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(
    channel,
    (MethodCall methodCall) => Future.value('some-image'),
  );
});

Comments

2

One additional thing to @呂學洲 answer.. is if you're writing a unit test and don't have reference to widget tester instance you can access the binder like below

TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger

Also make sure to wait for binder to initialize in the begging of the test like below

TestWidgetsFlutterBinding.ensureInitialized();

And to grab method call you can do:

final binaryBinding = TestDefaultBinaryMessengerBinding.instance;
pluginChannel = MethodChannel('channelName');

binaryBinding!.defaultBinaryMessenger.setMockMethodCallHandler(pluginChannel,
  (MethodCall methodCall) async {
    switch (methodCall.method) {
      case 'call 1':
        return  mockValue;
      default:
        return null;
    }
  },
);

Hope that helps.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.