skip to Main Content

I have tried Flutter Image Picker integration tests and How to test ImagePicker in Flutter Driver?. I am using ImagePicker plugin as below:

final result = await ImagePicker().getImage(source: ImageSource.gallery);

I have tried above solution, still the image picker opens gallery on emulator and never returns to the app for continuing testing.

Edit
Below is my sample code to mock, but no handler is called.


mockImagePicker(WidgetTester tester){
  print("Setting mockImagePicker starts");
  const MethodChannel channel =
  MethodChannel('plugins.flutter.io/image_picker');

  handler(MethodCall methodCall) async {
    print("Called method in mock method call is: ${methodCall.method}");
    print("mock handler called handler");
    ByteData data = await rootBundle.load('images/SplashScreen.png');
    Uint8List bytes = data.buffer.asUint8List();
    Directory tempDir = await getTemporaryDirectory();
    File file = await File('${tempDir.path}/tmp.tmp', ).writeAsBytes(bytes);
    print(file.path);
    return file.path;
  };

  channel.setMockMethodCallHandler((MethodCall methodCall) async {
    print("mock handler called setMockMethodCallHandler");
    return <String, String>{
      'type': 'image',
      'path': '/example/path',
    };
  });

  IntegrationTestWidgetsFlutterBinding?.instance?.defaultBinaryMessenger
      ?.setMockMethodCallHandler(channel, handler);
  tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(channel, (message) async {
    print("type 2 mock image");
    return await handler(message);
  });

}

Can anybody help what else am I missing?

2

Answers


  1. That code assumes that image_picker uses a method channel called plugins.flutter.io/image_picker, which hasn’t been true for a while. As explained in the Flutter docs, you should not mock the internal method channels of plugins, for exactly this reason. The code you are trying to use would have worked in the past, but no longer does because it is assuming internal plugin implementation details never change, which isn’t the case.

    As explained in that document, you should wrap your call to the plugin in something mockable, since then your code doesn’t rely on internal details of a package you don’t control. Failing that you could (also as explained in the docs) set a different platform implementation for the plugin (via ImagePickerPlatform.instance), but that is also fragile to changes in plugin implementation details.

    Login or Signup to reply.
  2. Define FakeImagePicker Class and override getImageFromSource and
    getMultiImageWithOptions method: and return temp image from asset folder.

    class FakeImagePicker extends ImagePickerPlatform {
      @override
      Future<XFile?> getImageFromSource({
        required ImageSource source,
        ImagePickerOptions options = const ImagePickerOptions(),
      }) async {
        final ByteData data = await rootBundle.load('assets/a1.png');
        final Uint8List bytes = data.buffer.asUint8List();
        final Directory tempDir = await getTemporaryDirectory();
        final File file = await File(
          '${tempDir.path}/doc.png',
        ).writeAsBytes(bytes);
    
        return XFile(file.path);
      }
    
      @override
      Future<List<XFile>> getMultiImageWithOptions({
        MultiImagePickerOptions options = const MultiImagePickerOptions(),
      }) async {
        final ByteData data = await rootBundle.load('assets/home/binoculars.png');
        final Uint8List bytes = data.buffer.asUint8List();
        final Directory tempDir = await getTemporaryDirectory();
        final File file = await File(
          '${tempDir.path}/binoculars.png',
        ).writeAsBytes(bytes);
        return <XFile>[
          XFile(
            file.path,
          )
        ];
      }
    }

    Then in your test set-up set ImagePickerPlatform to FakeImagePicker

    setUp(() {
        ImagePickerPlatform.instance = FakeImagePicker();
      });

    Then in your test case simply tap on image upload button it will mock that particular method:

       testWidget(tester){
    
          await tester.tap(find.byKey(uploadKey(docType)));
          await tester.pumpAndSettle();
             
         }

    And if you are also using FilePicker library to use pick file then u
    can also mock FilePicker library and call this mockFilePicker in your test setup.

      void mockFilePicker(String fileName) {
        const MethodChannel channelFilePicker =
            MethodChannel('miguelruivo.flutter.plugins.filepicker');
    
        TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger
            .setMockMethodCallHandler(
          channelFilePicker,
          (MethodCall methodCall) async {
            final ByteData data = await rootBundle.load('assets/home/$fileName');
            final Uint8List bytes = data.buffer.asUint8List();
            final Directory tempDir = await getTemporaryDirectory();
            final File file = await File(
              '${tempDir.path}/tmp.tmp',
            ).writeAsBytes(bytes);
    
            return [
              {
                'name': fileName,
                'path': file.path,
                'bytes': bytes,
                'size': bytes.lengthInBytes,
              }
            ];
          },
        );
      }

    I Hope this would be clear how to mock image picker from ImagePicker
    and FilePicker.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search