flutterflutter-integration-testflutter-image-picker

Mocking ImagePicker in flutter integration_tests not working


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?


Solution

  • 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.