[image_picker] Switch unit tests to mock plaform implementation (#5706)

`image_picker`'s app-facing tests were never updated during federation to
use a mock platform implementation, and instead were still mocking method
channels. That makes them fragile to implementation details of the
default method channel implementation that is part of another package,
and thus subject to breakage when the method channel changes.

This converts them to using a mock platform implementation, so it's only
testing the layer within this package.

Removes some tests that were testing things that only made sense at the
method channel layer.

Adds argument assertions that there were tests for, but were previously
only enforced in the implementations. As these are API constraints, they
should be enforced at the API layer, not at each implementation's layer
as they currently are.
diff --git a/packages/image_picker/image_picker/CHANGELOG.md b/packages/image_picker/image_picker/CHANGELOG.md
index 156b9a3..36a47b1 100644
--- a/packages/image_picker/image_picker/CHANGELOG.md
+++ b/packages/image_picker/image_picker/CHANGELOG.md
@@ -1,3 +1,10 @@
+## 0.8.5+3
+
+* Adds argument error assertions to the app-facing package, to ensure
+  consistency across platform implementations.
+* Updates tests to use a mock platform instead of relying on default
+  method channel implementation internals.
+
 ## 0.8.5+2
 
 * Minor fixes for new analysis options.
diff --git a/packages/image_picker/image_picker/lib/image_picker.dart b/packages/image_picker/image_picker/lib/image_picker.dart
index 5bc99d7..84c6490 100755
--- a/packages/image_picker/image_picker/lib/image_picker.dart
+++ b/packages/image_picker/image_picker/lib/image_picker.dart
@@ -207,6 +207,17 @@
     int? imageQuality,
     CameraDevice preferredCameraDevice = CameraDevice.rear,
   }) {
+    if (imageQuality != null && (imageQuality < 0 || imageQuality > 100)) {
+      throw ArgumentError.value(
+          imageQuality, 'imageQuality', 'must be between 0 and 100');
+    }
+    if (maxWidth != null && maxWidth < 0) {
+      throw ArgumentError.value(maxWidth, 'maxWidth', 'cannot be negative');
+    }
+    if (maxHeight != null && maxHeight < 0) {
+      throw ArgumentError.value(maxHeight, 'maxHeight', 'cannot be negative');
+    }
+
     return platform.getImage(
       source: source,
       maxWidth: maxWidth,
@@ -245,6 +256,17 @@
     double? maxHeight,
     int? imageQuality,
   }) {
+    if (imageQuality != null && (imageQuality < 0 || imageQuality > 100)) {
+      throw ArgumentError.value(
+          imageQuality, 'imageQuality', 'must be between 0 and 100');
+    }
+    if (maxWidth != null && maxWidth < 0) {
+      throw ArgumentError.value(maxWidth, 'maxWidth', 'cannot be negative');
+    }
+    if (maxHeight != null && maxHeight < 0) {
+      throw ArgumentError.value(maxHeight, 'maxHeight', 'cannot be negative');
+    }
+
     return platform.getMultiImage(
       maxWidth: maxWidth,
       maxHeight: maxHeight,
diff --git a/packages/image_picker/image_picker/pubspec.yaml b/packages/image_picker/image_picker/pubspec.yaml
index cc34d8a..9d0cede 100755
--- a/packages/image_picker/image_picker/pubspec.yaml
+++ b/packages/image_picker/image_picker/pubspec.yaml
@@ -3,7 +3,7 @@
   library, and taking new pictures with the camera.
 repository: https://github.com/flutter/plugins/tree/main/packages/image_picker/image_picker
 issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+image_picker%22
-version: 0.8.5+2
+version: 0.8.5+3
 
 environment:
   sdk: ">=2.14.0 <3.0.0"
@@ -28,6 +28,8 @@
   image_picker_platform_interface: ^2.3.0
 
 dev_dependencies:
+  build_runner: ^2.1.10
+  cross_file: ^0.3.1+1 # Mockito generates a direct include.
   flutter_test:
     sdk: flutter
   mockito: ^5.0.0
diff --git a/packages/image_picker/image_picker/test/image_picker_deprecated_test.dart b/packages/image_picker/image_picker/test/image_picker_deprecated_test.dart
index 00049e1..b3db080 100644
--- a/packages/image_picker/image_picker/test/image_picker_deprecated_test.dart
+++ b/packages/image_picker/image_picker/test/image_picker_deprecated_test.dart
@@ -14,63 +14,46 @@
 import 'package:mockito/mockito.dart';
 import 'package:plugin_platform_interface/plugin_platform_interface.dart';
 
+import 'image_picker_test.mocks.dart' as base_mock;
+
+// Add the mixin to make the platform interface accept the mock.
+class MockImagePickerPlatform extends base_mock.MockImagePickerPlatform
+    with MockPlatformInterfaceMixin {}
+
 void main() {
-  TestWidgetsFlutterBinding.ensureInitialized();
+  group('ImagePicker', () {
+    late MockImagePickerPlatform mockPlatform;
 
-  group('$ImagePicker', () {
-    const MethodChannel channel =
-        MethodChannel('plugins.flutter.io/image_picker');
-
-    final List<MethodCall> log = <MethodCall>[];
-
-    final ImagePicker picker = ImagePicker();
-
-    test('ImagePicker platform instance overrides the actual platform used',
-        () {
-      final ImagePickerPlatform savedPlatform = ImagePickerPlatform.instance;
-      final MockPlatform mockPlatform = MockPlatform();
+    setUp(() {
+      mockPlatform = MockImagePickerPlatform();
       ImagePickerPlatform.instance = mockPlatform;
-      expect(ImagePicker.platform, mockPlatform);
-      ImagePickerPlatform.instance = savedPlatform;
     });
 
     group('#Single image/video', () {
       setUp(() {
-        channel.setMockMethodCallHandler((MethodCall methodCall) async {
-          log.add(methodCall);
-          return '';
-        });
-
-        log.clear();
+        when(mockPlatform.pickImage(
+                source: anyNamed('source'),
+                maxWidth: anyNamed('maxWidth'),
+                maxHeight: anyNamed('maxHeight'),
+                imageQuality: anyNamed('imageQuality'),
+                preferredCameraDevice: anyNamed('preferredCameraDevice')))
+            .thenAnswer((Invocation _) async => null);
       });
 
       group('#pickImage', () {
         test('passes the image source argument correctly', () async {
+          final ImagePicker picker = ImagePicker();
           await picker.getImage(source: ImageSource.camera);
           await picker.getImage(source: ImageSource.gallery);
 
-          expect(
-            log,
-            <Matcher>[
-              isMethodCall('pickImage', arguments: <String, dynamic>{
-                'source': 0,
-                'maxWidth': null,
-                'maxHeight': null,
-                'imageQuality': null,
-                'cameraDevice': 0
-              }),
-              isMethodCall('pickImage', arguments: <String, dynamic>{
-                'source': 1,
-                'maxWidth': null,
-                'maxHeight': null,
-                'imageQuality': null,
-                'cameraDevice': 0
-              }),
-            ],
-          );
+          verifyInOrder(<Object>[
+            mockPlatform.pickImage(source: ImageSource.camera),
+            mockPlatform.pickImage(source: ImageSource.gallery),
+          ]);
         });
 
         test('passes the width and height arguments correctly', () async {
+          final ImagePicker picker = ImagePicker();
           await picker.getImage(source: ImageSource.camera);
           await picker.getImage(
             source: ImageSource.camera,
@@ -95,277 +78,182 @@
               maxHeight: 20.0,
               imageQuality: 70);
 
-          expect(
-            log,
-            <Matcher>[
-              isMethodCall('pickImage', arguments: <String, dynamic>{
-                'source': 0,
-                'maxWidth': null,
-                'maxHeight': null,
-                'imageQuality': null,
-                'cameraDevice': 0
-              }),
-              isMethodCall('pickImage', arguments: <String, dynamic>{
-                'source': 0,
-                'maxWidth': 10.0,
-                'maxHeight': null,
-                'imageQuality': null,
-                'cameraDevice': 0
-              }),
-              isMethodCall('pickImage', arguments: <String, dynamic>{
-                'source': 0,
-                'maxWidth': null,
-                'maxHeight': 10.0,
-                'imageQuality': null,
-                'cameraDevice': 0
-              }),
-              isMethodCall('pickImage', arguments: <String, dynamic>{
-                'source': 0,
-                'maxWidth': 10.0,
-                'maxHeight': 20.0,
-                'imageQuality': null,
-                'cameraDevice': 0
-              }),
-              isMethodCall('pickImage', arguments: <String, dynamic>{
-                'source': 0,
-                'maxWidth': 10.0,
-                'maxHeight': null,
-                'imageQuality': 70,
-                'cameraDevice': 0
-              }),
-              isMethodCall('pickImage', arguments: <String, dynamic>{
-                'source': 0,
-                'maxWidth': null,
-                'maxHeight': 10.0,
-                'imageQuality': 70,
-                'cameraDevice': 0
-              }),
-              isMethodCall('pickImage', arguments: <String, dynamic>{
-                'source': 0,
-                'maxWidth': 10.0,
-                'maxHeight': 20.0,
-                'imageQuality': 70,
-                'cameraDevice': 0
-              }),
-            ],
-          );
+          verifyInOrder(<Object>[
+            mockPlatform.pickImage(
+                source: ImageSource.camera,
+                maxWidth: null,
+                maxHeight: null,
+                imageQuality: null),
+            mockPlatform.pickImage(
+                source: ImageSource.camera,
+                maxWidth: 10.0,
+                maxHeight: null,
+                imageQuality: null),
+            mockPlatform.pickImage(
+                source: ImageSource.camera,
+                maxWidth: null,
+                maxHeight: 10.0,
+                imageQuality: null),
+            mockPlatform.pickImage(
+                source: ImageSource.camera,
+                maxWidth: 10.0,
+                maxHeight: 20.0,
+                imageQuality: null),
+            mockPlatform.pickImage(
+                source: ImageSource.camera,
+                maxWidth: 10.0,
+                maxHeight: null,
+                imageQuality: 70),
+            mockPlatform.pickImage(
+                source: ImageSource.camera,
+                maxWidth: null,
+                maxHeight: 10.0,
+                imageQuality: 70),
+            mockPlatform.pickImage(
+                source: ImageSource.camera,
+                maxWidth: 10.0,
+                maxHeight: 20.0,
+                imageQuality: 70),
+          ]);
         });
 
-        test('does not accept a negative width or height argument', () {
-          expect(
-            picker.getImage(source: ImageSource.camera, maxWidth: -1.0),
-            throwsArgumentError,
-          );
-
-          expect(
-            picker.getImage(source: ImageSource.camera, maxHeight: -1.0),
-            throwsArgumentError,
-          );
-        });
-
-        test('handles a null image path response gracefully', () async {
-          channel.setMockMethodCallHandler((MethodCall methodCall) => null);
+        test('handles a null image file response gracefully', () async {
+          final ImagePicker picker = ImagePicker();
 
           expect(await picker.getImage(source: ImageSource.gallery), isNull);
           expect(await picker.getImage(source: ImageSource.camera), isNull);
         });
 
         test('camera position defaults to back', () async {
+          final ImagePicker picker = ImagePicker();
           await picker.getImage(source: ImageSource.camera);
 
-          expect(
-            log,
-            <Matcher>[
-              isMethodCall('pickImage', arguments: <String, dynamic>{
-                'source': 0,
-                'maxWidth': null,
-                'maxHeight': null,
-                'imageQuality': null,
-                'cameraDevice': 0,
-              }),
-            ],
-          );
+          verify(mockPlatform.pickImage(
+              source: ImageSource.camera,
+              preferredCameraDevice: CameraDevice.rear));
         });
 
         test('camera position can set to front', () async {
+          final ImagePicker picker = ImagePicker();
           await picker.getImage(
               source: ImageSource.camera,
               preferredCameraDevice: CameraDevice.front);
 
-          expect(
-            log,
-            <Matcher>[
-              isMethodCall('pickImage', arguments: <String, dynamic>{
-                'source': 0,
-                'maxWidth': null,
-                'maxHeight': null,
-                'imageQuality': null,
-                'cameraDevice': 1,
-              }),
-            ],
-          );
+          verify(mockPlatform.pickImage(
+              source: ImageSource.camera,
+              preferredCameraDevice: CameraDevice.front));
         });
       });
 
       group('#pickVideo', () {
+        setUp(() {
+          when(mockPlatform.pickVideo(
+                  source: anyNamed('source'),
+                  preferredCameraDevice: anyNamed('preferredCameraDevice'),
+                  maxDuration: anyNamed('maxDuration')))
+              .thenAnswer((Invocation _) async => null);
+        });
+
         test('passes the image source argument correctly', () async {
+          final ImagePicker picker = ImagePicker();
           await picker.getVideo(source: ImageSource.camera);
           await picker.getVideo(source: ImageSource.gallery);
 
-          expect(
-            log,
-            <Matcher>[
-              isMethodCall('pickVideo', arguments: <String, dynamic>{
-                'source': 0,
-                'cameraDevice': 0,
-                'maxDuration': null,
-              }),
-              isMethodCall('pickVideo', arguments: <String, dynamic>{
-                'source': 1,
-                'cameraDevice': 0,
-                'maxDuration': null,
-              }),
-            ],
-          );
+          verifyInOrder(<Object>[
+            mockPlatform.pickVideo(source: ImageSource.camera),
+            mockPlatform.pickVideo(source: ImageSource.gallery),
+          ]);
         });
 
         test('passes the duration argument correctly', () async {
+          final ImagePicker picker = ImagePicker();
           await picker.getVideo(source: ImageSource.camera);
           await picker.getVideo(
               source: ImageSource.camera,
               maxDuration: const Duration(seconds: 10));
-          await picker.getVideo(
-              source: ImageSource.camera,
-              maxDuration: const Duration(minutes: 1));
-          await picker.getVideo(
-              source: ImageSource.camera,
-              maxDuration: const Duration(hours: 1));
-          expect(
-            log,
-            <Matcher>[
-              isMethodCall('pickVideo', arguments: <String, dynamic>{
-                'source': 0,
-                'maxDuration': null,
-                'cameraDevice': 0,
-              }),
-              isMethodCall('pickVideo', arguments: <String, dynamic>{
-                'source': 0,
-                'maxDuration': 10,
-                'cameraDevice': 0,
-              }),
-              isMethodCall('pickVideo', arguments: <String, dynamic>{
-                'source': 0,
-                'maxDuration': 60,
-                'cameraDevice': 0,
-              }),
-              isMethodCall('pickVideo', arguments: <String, dynamic>{
-                'source': 0,
-                'maxDuration': 3600,
-                'cameraDevice': 0,
-              }),
-            ],
-          );
+
+          verifyInOrder(<Object>[
+            mockPlatform.pickVideo(
+                source: ImageSource.camera,
+                preferredCameraDevice: CameraDevice.rear,
+                maxDuration: null),
+            mockPlatform.pickVideo(
+                source: ImageSource.camera,
+                preferredCameraDevice: CameraDevice.rear,
+                maxDuration: const Duration(seconds: 10)),
+          ]);
         });
 
-        test('handles a null video path response gracefully', () async {
-          channel.setMockMethodCallHandler((MethodCall methodCall) => null);
+        test('handles a null video file response gracefully', () async {
+          final ImagePicker picker = ImagePicker();
 
           expect(await picker.getVideo(source: ImageSource.gallery), isNull);
           expect(await picker.getVideo(source: ImageSource.camera), isNull);
         });
 
         test('camera position defaults to back', () async {
+          final ImagePicker picker = ImagePicker();
           await picker.getVideo(source: ImageSource.camera);
 
-          expect(
-            log,
-            <Matcher>[
-              isMethodCall('pickVideo', arguments: <String, dynamic>{
-                'source': 0,
-                'cameraDevice': 0,
-                'maxDuration': null,
-              }),
-            ],
-          );
+          verify(mockPlatform.pickVideo(
+              source: ImageSource.camera,
+              preferredCameraDevice: CameraDevice.rear));
         });
 
         test('camera position can set to front', () async {
+          final ImagePicker picker = ImagePicker();
           await picker.getVideo(
               source: ImageSource.camera,
               preferredCameraDevice: CameraDevice.front);
 
-          expect(
-            log,
-            <Matcher>[
-              isMethodCall('pickVideo', arguments: <String, dynamic>{
-                'source': 0,
-                'maxDuration': null,
-                'cameraDevice': 1,
-              }),
-            ],
-          );
+          verify(mockPlatform.pickVideo(
+              source: ImageSource.camera,
+              preferredCameraDevice: CameraDevice.front));
         });
       });
 
       group('#retrieveLostData', () {
         test('retrieveLostData get success response', () async {
-          channel.setMockMethodCallHandler((MethodCall methodCall) async {
-            return <String, String>{
-              'type': 'image',
-              'path': '/example/path',
-            };
-          });
+          final ImagePicker picker = ImagePicker();
+          when(mockPlatform.retrieveLostData()).thenAnswer(
+              (Invocation _) async => LostData(
+                  file: PickedFile('/example/path'), type: RetrieveType.image));
+
           final LostData response = await picker.getLostData();
+
           expect(response.type, RetrieveType.image);
           expect(response.file!.path, '/example/path');
         });
 
         test('retrieveLostData get error response', () async {
-          channel.setMockMethodCallHandler((MethodCall methodCall) async {
-            return <String, String>{
-              'type': 'video',
-              'errorCode': 'test_error_code',
-              'errorMessage': 'test_error_message',
-            };
-          });
+          final ImagePicker picker = ImagePicker();
+          when(mockPlatform.retrieveLostData()).thenAnswer(
+              (Invocation _) async => LostData(
+                  exception: PlatformException(
+                      code: 'test_error_code', message: 'test_error_message'),
+                  type: RetrieveType.video));
+
           final LostData response = await picker.getLostData();
+
           expect(response.type, RetrieveType.video);
           expect(response.exception!.code, 'test_error_code');
           expect(response.exception!.message, 'test_error_message');
         });
-
-        test('retrieveLostData get null response', () async {
-          channel.setMockMethodCallHandler((MethodCall methodCall) async {
-            return null;
-          });
-          expect((await picker.getLostData()).isEmpty, true);
-        });
-
-        test('retrieveLostData get both path and error should throw', () async {
-          channel.setMockMethodCallHandler((MethodCall methodCall) async {
-            return <String, String>{
-              'type': 'video',
-              'errorCode': 'test_error_code',
-              'errorMessage': 'test_error_message',
-              'path': '/example/path',
-            };
-          });
-          expect(picker.getLostData(), throwsAssertionError);
-        });
       });
     });
 
     group('Multi images', () {
       setUp(() {
-        channel.setMockMethodCallHandler((MethodCall methodCall) async {
-          log.add(methodCall);
-          return <dynamic>[];
-        });
-        log.clear();
+        when(mockPlatform.pickMultiImage(
+                maxWidth: anyNamed('maxWidth'),
+                maxHeight: anyNamed('maxHeight'),
+                imageQuality: anyNamed('imageQuality')))
+            .thenAnswer((Invocation _) async => null);
       });
 
       group('#pickMultiImage', () {
         test('passes the width and height arguments correctly', () async {
+          final ImagePicker picker = ImagePicker();
           await picker.getMultiImage();
           await picker.getMultiImage(
             maxWidth: 10.0,
@@ -388,62 +276,26 @@
           await picker.getMultiImage(
               maxWidth: 10.0, maxHeight: 20.0, imageQuality: 70);
 
-          expect(
-            log,
-            <Matcher>[
-              isMethodCall('pickMultiImage', arguments: <String, dynamic>{
-                'maxWidth': null,
-                'maxHeight': null,
-                'imageQuality': null,
-              }),
-              isMethodCall('pickMultiImage', arguments: <String, dynamic>{
-                'maxWidth': 10.0,
-                'maxHeight': null,
-                'imageQuality': null,
-              }),
-              isMethodCall('pickMultiImage', arguments: <String, dynamic>{
-                'maxWidth': null,
-                'maxHeight': 10.0,
-                'imageQuality': null,
-              }),
-              isMethodCall('pickMultiImage', arguments: <String, dynamic>{
-                'maxWidth': 10.0,
-                'maxHeight': 20.0,
-                'imageQuality': null,
-              }),
-              isMethodCall('pickMultiImage', arguments: <String, dynamic>{
-                'maxWidth': 10.0,
-                'maxHeight': null,
-                'imageQuality': 70,
-              }),
-              isMethodCall('pickMultiImage', arguments: <String, dynamic>{
-                'maxWidth': null,
-                'maxHeight': 10.0,
-                'imageQuality': 70,
-              }),
-              isMethodCall('pickMultiImage', arguments: <String, dynamic>{
-                'maxWidth': 10.0,
-                'maxHeight': 20.0,
-                'imageQuality': 70,
-              }),
-            ],
-          );
+          verifyInOrder(<Object>[
+            mockPlatform.pickMultiImage(
+                maxWidth: null, maxHeight: null, imageQuality: null),
+            mockPlatform.pickMultiImage(
+                maxWidth: 10.0, maxHeight: null, imageQuality: null),
+            mockPlatform.pickMultiImage(
+                maxWidth: null, maxHeight: 10.0, imageQuality: null),
+            mockPlatform.pickMultiImage(
+                maxWidth: 10.0, maxHeight: 20.0, imageQuality: null),
+            mockPlatform.pickMultiImage(
+                maxWidth: 10.0, maxHeight: null, imageQuality: 70),
+            mockPlatform.pickMultiImage(
+                maxWidth: null, maxHeight: 10.0, imageQuality: 70),
+            mockPlatform.pickMultiImage(
+                maxWidth: 10.0, maxHeight: 20.0, imageQuality: 70),
+          ]);
         });
 
-        test('does not accept a negative width or height argument', () {
-          expect(
-            picker.getMultiImage(maxWidth: -1.0),
-            throwsArgumentError,
-          );
-
-          expect(
-            picker.getMultiImage(maxHeight: -1.0),
-            throwsArgumentError,
-          );
-        });
-
-        test('handles a null image path response gracefully', () async {
-          channel.setMockMethodCallHandler((MethodCall methodCall) => null);
+        test('handles a null image file response gracefully', () async {
+          final ImagePicker picker = ImagePicker();
 
           expect(await picker.getMultiImage(), isNull);
           expect(await picker.getMultiImage(), isNull);
@@ -452,7 +304,3 @@
     });
   });
 }
-
-class MockPlatform extends Mock
-    with MockPlatformInterfaceMixin
-    implements ImagePickerPlatform {}
diff --git a/packages/image_picker/image_picker/test/image_picker_test.dart b/packages/image_picker/image_picker/test/image_picker_test.dart
index b41fbe3..f981195 100644
--- a/packages/image_picker/image_picker/test/image_picker_test.dart
+++ b/packages/image_picker/image_picker/test/image_picker_test.dart
@@ -6,66 +6,51 @@
 import 'package:flutter_test/flutter_test.dart';
 import 'package:image_picker/image_picker.dart';
 import 'package:image_picker_platform_interface/image_picker_platform_interface.dart';
+import 'package:mockito/annotations.dart';
 import 'package:mockito/mockito.dart';
 import 'package:plugin_platform_interface/plugin_platform_interface.dart';
 
+import 'image_picker_test.mocks.dart' as base_mock;
+
+// Add the mixin to make the platform interface accept the mock.
+class MockImagePickerPlatform extends base_mock.MockImagePickerPlatform
+    with MockPlatformInterfaceMixin {}
+
+@GenerateMocks(<Type>[ImagePickerPlatform])
 void main() {
-  TestWidgetsFlutterBinding.ensureInitialized();
+  group('ImagePicker', () {
+    late MockImagePickerPlatform mockPlatform;
 
-  group('$ImagePicker', () {
-    const MethodChannel channel =
-        MethodChannel('plugins.flutter.io/image_picker');
-
-    final List<MethodCall> log = <MethodCall>[];
-
-    final ImagePicker picker = ImagePicker();
-
-    test('ImagePicker platform instance overrides the actual platform used',
-        () {
-      final ImagePickerPlatform savedPlatform = ImagePickerPlatform.instance;
-      final MockPlatform mockPlatform = MockPlatform();
+    setUp(() {
+      mockPlatform = MockImagePickerPlatform();
       ImagePickerPlatform.instance = mockPlatform;
-      expect(ImagePicker.platform, mockPlatform);
-      ImagePickerPlatform.instance = savedPlatform;
     });
 
     group('#Single image/video', () {
-      setUp(() {
-        channel.setMockMethodCallHandler((MethodCall methodCall) async {
-          log.add(methodCall);
-          return '';
+      group('#pickImage', () {
+        setUp(() {
+          when(mockPlatform.getImage(
+                  source: anyNamed('source'),
+                  maxWidth: anyNamed('maxWidth'),
+                  maxHeight: anyNamed('maxHeight'),
+                  imageQuality: anyNamed('imageQuality'),
+                  preferredCameraDevice: anyNamed('preferredCameraDevice')))
+              .thenAnswer((Invocation _) async => null);
         });
 
-        log.clear();
-      });
-
-      group('#pickImage', () {
         test('passes the image source argument correctly', () async {
+          final ImagePicker picker = ImagePicker();
           await picker.pickImage(source: ImageSource.camera);
           await picker.pickImage(source: ImageSource.gallery);
 
-          expect(
-            log,
-            <Matcher>[
-              isMethodCall('pickImage', arguments: <String, dynamic>{
-                'source': 0,
-                'maxWidth': null,
-                'maxHeight': null,
-                'imageQuality': null,
-                'cameraDevice': 0
-              }),
-              isMethodCall('pickImage', arguments: <String, dynamic>{
-                'source': 1,
-                'maxWidth': null,
-                'maxHeight': null,
-                'imageQuality': null,
-                'cameraDevice': 0
-              }),
-            ],
-          );
+          verifyInOrder(<Object>[
+            mockPlatform.getImage(source: ImageSource.camera),
+            mockPlatform.getImage(source: ImageSource.gallery),
+          ]);
         });
 
         test('passes the width and height arguments correctly', () async {
+          final ImagePicker picker = ImagePicker();
           await picker.pickImage(source: ImageSource.camera);
           await picker.pickImage(
             source: ImageSource.camera,
@@ -90,242 +75,184 @@
               maxHeight: 20.0,
               imageQuality: 70);
 
-          expect(
-            log,
-            <Matcher>[
-              isMethodCall('pickImage', arguments: <String, dynamic>{
-                'source': 0,
-                'maxWidth': null,
-                'maxHeight': null,
-                'imageQuality': null,
-                'cameraDevice': 0
-              }),
-              isMethodCall('pickImage', arguments: <String, dynamic>{
-                'source': 0,
-                'maxWidth': 10.0,
-                'maxHeight': null,
-                'imageQuality': null,
-                'cameraDevice': 0
-              }),
-              isMethodCall('pickImage', arguments: <String, dynamic>{
-                'source': 0,
-                'maxWidth': null,
-                'maxHeight': 10.0,
-                'imageQuality': null,
-                'cameraDevice': 0
-              }),
-              isMethodCall('pickImage', arguments: <String, dynamic>{
-                'source': 0,
-                'maxWidth': 10.0,
-                'maxHeight': 20.0,
-                'imageQuality': null,
-                'cameraDevice': 0
-              }),
-              isMethodCall('pickImage', arguments: <String, dynamic>{
-                'source': 0,
-                'maxWidth': 10.0,
-                'maxHeight': null,
-                'imageQuality': 70,
-                'cameraDevice': 0
-              }),
-              isMethodCall('pickImage', arguments: <String, dynamic>{
-                'source': 0,
-                'maxWidth': null,
-                'maxHeight': 10.0,
-                'imageQuality': 70,
-                'cameraDevice': 0
-              }),
-              isMethodCall('pickImage', arguments: <String, dynamic>{
-                'source': 0,
-                'maxWidth': 10.0,
-                'maxHeight': 20.0,
-                'imageQuality': 70,
-                'cameraDevice': 0
-              }),
-            ],
-          );
+          verifyInOrder(<Object>[
+            mockPlatform.getImage(
+                source: ImageSource.camera,
+                maxWidth: null,
+                maxHeight: null,
+                imageQuality: null),
+            mockPlatform.getImage(
+                source: ImageSource.camera,
+                maxWidth: 10.0,
+                maxHeight: null,
+                imageQuality: null),
+            mockPlatform.getImage(
+                source: ImageSource.camera,
+                maxWidth: null,
+                maxHeight: 10.0,
+                imageQuality: null),
+            mockPlatform.getImage(
+                source: ImageSource.camera,
+                maxWidth: 10.0,
+                maxHeight: 20.0,
+                imageQuality: null),
+            mockPlatform.getImage(
+                source: ImageSource.camera,
+                maxWidth: 10.0,
+                maxHeight: null,
+                imageQuality: 70),
+            mockPlatform.getImage(
+                source: ImageSource.camera,
+                maxWidth: null,
+                maxHeight: 10.0,
+                imageQuality: 70),
+            mockPlatform.getImage(
+                source: ImageSource.camera,
+                maxWidth: 10.0,
+                maxHeight: 20.0,
+                imageQuality: 70),
+          ]);
         });
 
         test('does not accept a negative width or height argument', () {
+          final ImagePicker picker = ImagePicker();
           expect(
-            picker.pickImage(source: ImageSource.camera, maxWidth: -1.0),
+            () => picker.pickImage(source: ImageSource.camera, maxWidth: -1.0),
             throwsArgumentError,
           );
 
           expect(
-            picker.pickImage(source: ImageSource.camera, maxHeight: -1.0),
+            () => picker.pickImage(source: ImageSource.camera, maxHeight: -1.0),
             throwsArgumentError,
           );
         });
 
-        test('handles a null image path response gracefully', () async {
-          channel.setMockMethodCallHandler((MethodCall methodCall) => null);
+        test('handles a null image file response gracefully', () async {
+          final ImagePicker picker = ImagePicker();
 
           expect(await picker.pickImage(source: ImageSource.gallery), isNull);
           expect(await picker.pickImage(source: ImageSource.camera), isNull);
         });
 
         test('camera position defaults to back', () async {
+          final ImagePicker picker = ImagePicker();
           await picker.pickImage(source: ImageSource.camera);
 
-          expect(
-            log,
-            <Matcher>[
-              isMethodCall('pickImage', arguments: <String, dynamic>{
-                'source': 0,
-                'maxWidth': null,
-                'maxHeight': null,
-                'imageQuality': null,
-                'cameraDevice': 0,
-              }),
-            ],
-          );
+          verify(mockPlatform.getImage(
+              source: ImageSource.camera,
+              preferredCameraDevice: CameraDevice.rear));
         });
 
         test('camera position can set to front', () async {
+          final ImagePicker picker = ImagePicker();
           await picker.pickImage(
               source: ImageSource.camera,
               preferredCameraDevice: CameraDevice.front);
 
-          expect(
-            log,
-            <Matcher>[
-              isMethodCall('pickImage', arguments: <String, dynamic>{
-                'source': 0,
-                'maxWidth': null,
-                'maxHeight': null,
-                'imageQuality': null,
-                'cameraDevice': 1,
-              }),
-            ],
-          );
+          verify(mockPlatform.getImage(
+              source: ImageSource.camera,
+              preferredCameraDevice: CameraDevice.front));
         });
       });
 
       group('#pickVideo', () {
+        setUp(() {
+          when(mockPlatform.getVideo(
+                  source: anyNamed('source'),
+                  preferredCameraDevice: anyNamed('preferredCameraDevice'),
+                  maxDuration: anyNamed('maxDuration')))
+              .thenAnswer((Invocation _) async => null);
+        });
+
         test('passes the image source argument correctly', () async {
+          final ImagePicker picker = ImagePicker();
           await picker.pickVideo(source: ImageSource.camera);
           await picker.pickVideo(source: ImageSource.gallery);
 
-          expect(
-            log,
-            <Matcher>[
-              isMethodCall('pickVideo', arguments: <String, dynamic>{
-                'source': 0,
-                'cameraDevice': 0,
-                'maxDuration': null,
-              }),
-              isMethodCall('pickVideo', arguments: <String, dynamic>{
-                'source': 1,
-                'cameraDevice': 0,
-                'maxDuration': null,
-              }),
-            ],
-          );
+          verifyInOrder(<Object>[
+            mockPlatform.getVideo(source: ImageSource.camera),
+            mockPlatform.getVideo(source: ImageSource.gallery),
+          ]);
         });
 
         test('passes the duration argument correctly', () async {
+          final ImagePicker picker = ImagePicker();
           await picker.pickVideo(source: ImageSource.camera);
           await picker.pickVideo(
               source: ImageSource.camera,
               maxDuration: const Duration(seconds: 10));
-          await picker.pickVideo(
-              source: ImageSource.camera,
-              maxDuration: const Duration(minutes: 1));
-          await picker.pickVideo(
-              source: ImageSource.camera,
-              maxDuration: const Duration(hours: 1));
-          expect(
-            log,
-            <Matcher>[
-              isMethodCall('pickVideo', arguments: <String, dynamic>{
-                'source': 0,
-                'maxDuration': null,
-                'cameraDevice': 0,
-              }),
-              isMethodCall('pickVideo', arguments: <String, dynamic>{
-                'source': 0,
-                'maxDuration': 10,
-                'cameraDevice': 0,
-              }),
-              isMethodCall('pickVideo', arguments: <String, dynamic>{
-                'source': 0,
-                'maxDuration': 60,
-                'cameraDevice': 0,
-              }),
-              isMethodCall('pickVideo', arguments: <String, dynamic>{
-                'source': 0,
-                'maxDuration': 3600,
-                'cameraDevice': 0,
-              }),
-            ],
-          );
+
+          verifyInOrder(<Object>[
+            mockPlatform.getVideo(
+                source: ImageSource.camera,
+                preferredCameraDevice: CameraDevice.rear,
+                maxDuration: null),
+            mockPlatform.getVideo(
+                source: ImageSource.camera,
+                preferredCameraDevice: CameraDevice.rear,
+                maxDuration: const Duration(seconds: 10)),
+          ]);
         });
 
-        test('handles a null video path response gracefully', () async {
-          channel.setMockMethodCallHandler((MethodCall methodCall) => null);
+        test('handles a null video file response gracefully', () async {
+          final ImagePicker picker = ImagePicker();
 
           expect(await picker.pickVideo(source: ImageSource.gallery), isNull);
           expect(await picker.pickVideo(source: ImageSource.camera), isNull);
         });
 
         test('camera position defaults to back', () async {
+          final ImagePicker picker = ImagePicker();
           await picker.pickVideo(source: ImageSource.camera);
 
-          expect(
-            log,
-            <Matcher>[
-              isMethodCall('pickVideo', arguments: <String, dynamic>{
-                'source': 0,
-                'cameraDevice': 0,
-                'maxDuration': null,
-              }),
-            ],
-          );
+          verify(mockPlatform.getVideo(
+              source: ImageSource.camera,
+              preferredCameraDevice: CameraDevice.rear));
         });
 
         test('camera position can set to front', () async {
+          final ImagePicker picker = ImagePicker();
           await picker.pickVideo(
               source: ImageSource.camera,
               preferredCameraDevice: CameraDevice.front);
 
-          expect(
-            log,
-            <Matcher>[
-              isMethodCall('pickVideo', arguments: <String, dynamic>{
-                'source': 0,
-                'maxDuration': null,
-                'cameraDevice': 1,
-              }),
-            ],
-          );
+          verify(mockPlatform.getVideo(
+              source: ImageSource.camera,
+              preferredCameraDevice: CameraDevice.front));
         });
       });
 
       group('#retrieveLostData', () {
         test('retrieveLostData get success response', () async {
-          channel.setMockMethodCallHandler((MethodCall methodCall) async {
-            return <String, String>{
-              'type': 'image',
-              'path': '/example/path',
-            };
-          });
+          final ImagePicker picker = ImagePicker();
+          final XFile lostFile = XFile('/example/path');
+          when(mockPlatform.getLostData()).thenAnswer((Invocation _) async =>
+              LostDataResponse(
+                  file: lostFile,
+                  files: <XFile>[lostFile],
+                  type: RetrieveType.image));
+
           final LostDataResponse response = await picker.retrieveLostData();
+
           expect(response.type, RetrieveType.image);
           expect(response.file!.path, '/example/path');
         });
 
         test('retrieveLostData should successfully retrieve multiple files',
             () async {
-          channel.setMockMethodCallHandler((MethodCall methodCall) async {
-            return <String, dynamic>{
-              'type': 'image',
-              'path': '/example/path1',
-              'pathList': <dynamic>['/example/path0', '/example/path1'],
-            };
-          });
+          final ImagePicker picker = ImagePicker();
+          final List<XFile> lostFiles = <XFile>[
+            XFile('/example/path0'),
+            XFile('/example/path1'),
+          ];
+          when(mockPlatform.getLostData()).thenAnswer((Invocation _) async =>
+              LostDataResponse(
+                  file: lostFiles.last,
+                  files: lostFiles,
+                  type: RetrieveType.image));
 
           final LostDataResponse response = await picker.retrieveLostData();
+
           expect(response.type, RetrieveType.image);
           expect(response.file, isNotNull);
           expect(response.file!.path, '/example/path1');
@@ -334,51 +261,34 @@
         });
 
         test('retrieveLostData get error response', () async {
-          channel.setMockMethodCallHandler((MethodCall methodCall) async {
-            return <String, String>{
-              'type': 'video',
-              'errorCode': 'test_error_code',
-              'errorMessage': 'test_error_message',
-            };
-          });
+          final ImagePicker picker = ImagePicker();
+          when(mockPlatform.getLostData()).thenAnswer((Invocation _) async =>
+              LostDataResponse(
+                  exception: PlatformException(
+                      code: 'test_error_code', message: 'test_error_message'),
+                  type: RetrieveType.video));
+
           final LostDataResponse response = await picker.retrieveLostData();
+
           expect(response.type, RetrieveType.video);
           expect(response.exception!.code, 'test_error_code');
           expect(response.exception!.message, 'test_error_message');
         });
-
-        test('retrieveLostData get null response', () async {
-          channel.setMockMethodCallHandler((MethodCall methodCall) async {
-            return null;
-          });
-          expect((await picker.retrieveLostData()).isEmpty, true);
-        });
-
-        test('retrieveLostData get both path and error should throw', () async {
-          channel.setMockMethodCallHandler((MethodCall methodCall) async {
-            return <String, String>{
-              'type': 'video',
-              'errorCode': 'test_error_code',
-              'errorMessage': 'test_error_message',
-              'path': '/example/path',
-            };
-          });
-          expect(picker.retrieveLostData(), throwsAssertionError);
-        });
       });
     });
 
     group('#Multi images', () {
       setUp(() {
-        channel.setMockMethodCallHandler((MethodCall methodCall) async {
-          log.add(methodCall);
-          return <dynamic>[];
-        });
-        log.clear();
+        when(mockPlatform.getMultiImage(
+                maxWidth: anyNamed('maxWidth'),
+                maxHeight: anyNamed('maxHeight'),
+                imageQuality: anyNamed('imageQuality')))
+            .thenAnswer((Invocation _) async => null);
       });
 
       group('#pickMultiImage', () {
         test('passes the width and height arguments correctly', () async {
+          final ImagePicker picker = ImagePicker();
           await picker.pickMultiImage();
           await picker.pickMultiImage(
             maxWidth: 10.0,
@@ -401,62 +311,39 @@
           await picker.pickMultiImage(
               maxWidth: 10.0, maxHeight: 20.0, imageQuality: 70);
 
-          expect(
-            log,
-            <Matcher>[
-              isMethodCall('pickMultiImage', arguments: <String, dynamic>{
-                'maxWidth': null,
-                'maxHeight': null,
-                'imageQuality': null,
-              }),
-              isMethodCall('pickMultiImage', arguments: <String, dynamic>{
-                'maxWidth': 10.0,
-                'maxHeight': null,
-                'imageQuality': null,
-              }),
-              isMethodCall('pickMultiImage', arguments: <String, dynamic>{
-                'maxWidth': null,
-                'maxHeight': 10.0,
-                'imageQuality': null,
-              }),
-              isMethodCall('pickMultiImage', arguments: <String, dynamic>{
-                'maxWidth': 10.0,
-                'maxHeight': 20.0,
-                'imageQuality': null,
-              }),
-              isMethodCall('pickMultiImage', arguments: <String, dynamic>{
-                'maxWidth': 10.0,
-                'maxHeight': null,
-                'imageQuality': 70,
-              }),
-              isMethodCall('pickMultiImage', arguments: <String, dynamic>{
-                'maxWidth': null,
-                'maxHeight': 10.0,
-                'imageQuality': 70,
-              }),
-              isMethodCall('pickMultiImage', arguments: <String, dynamic>{
-                'maxWidth': 10.0,
-                'maxHeight': 20.0,
-                'imageQuality': 70,
-              }),
-            ],
-          );
+          verifyInOrder(<Object>[
+            mockPlatform.getMultiImage(
+                maxWidth: null, maxHeight: null, imageQuality: null),
+            mockPlatform.getMultiImage(
+                maxWidth: 10.0, maxHeight: null, imageQuality: null),
+            mockPlatform.getMultiImage(
+                maxWidth: null, maxHeight: 10.0, imageQuality: null),
+            mockPlatform.getMultiImage(
+                maxWidth: 10.0, maxHeight: 20.0, imageQuality: null),
+            mockPlatform.getMultiImage(
+                maxWidth: 10.0, maxHeight: null, imageQuality: 70),
+            mockPlatform.getMultiImage(
+                maxWidth: null, maxHeight: 10.0, imageQuality: 70),
+            mockPlatform.getMultiImage(
+                maxWidth: 10.0, maxHeight: 20.0, imageQuality: 70),
+          ]);
         });
 
         test('does not accept a negative width or height argument', () {
+          final ImagePicker picker = ImagePicker();
           expect(
-            picker.pickMultiImage(maxWidth: -1.0),
+            () => picker.pickMultiImage(maxWidth: -1.0),
             throwsArgumentError,
           );
 
           expect(
-            picker.pickMultiImage(maxHeight: -1.0),
+            () => picker.pickMultiImage(maxHeight: -1.0),
             throwsArgumentError,
           );
         });
 
-        test('handles a null image path response gracefully', () async {
-          channel.setMockMethodCallHandler((MethodCall methodCall) => null);
+        test('handles a null image file response gracefully', () async {
+          final ImagePicker picker = ImagePicker();
 
           expect(await picker.pickMultiImage(), isNull);
           expect(await picker.pickMultiImage(), isNull);
@@ -465,7 +352,3 @@
     });
   });
 }
-
-class MockPlatform extends Mock
-    with MockPlatformInterfaceMixin
-    implements ImagePickerPlatform {}
diff --git a/packages/image_picker/image_picker/test/image_picker_test.mocks.dart b/packages/image_picker/image_picker/test/image_picker_test.mocks.dart
new file mode 100644
index 0000000..641a104
--- /dev/null
+++ b/packages/image_picker/image_picker/test/image_picker_test.mocks.dart
@@ -0,0 +1,136 @@
+// Mocks generated by Mockito 5.1.0 from annotations
+// in image_picker/test/image_picker_test.dart.
+// Do not manually edit this file.
+
+import 'dart:async' as _i4;
+
+import 'package:cross_file/cross_file.dart' as _i5;
+import 'package:image_picker_platform_interface/src/platform_interface/image_picker_platform.dart'
+    as _i3;
+import 'package:image_picker_platform_interface/src/types/types.dart' as _i2;
+import 'package:mockito/mockito.dart' as _i1;
+
+// ignore_for_file: type=lint
+// ignore_for_file: avoid_redundant_argument_values
+// ignore_for_file: avoid_setters_without_getters
+// ignore_for_file: comment_references
+// ignore_for_file: implementation_imports
+// ignore_for_file: invalid_use_of_visible_for_testing_member
+// ignore_for_file: prefer_const_constructors
+// ignore_for_file: unnecessary_parenthesis
+// ignore_for_file: camel_case_types
+
+class _FakeLostData_0 extends _i1.Fake implements _i2.LostData {}
+
+class _FakeLostDataResponse_1 extends _i1.Fake implements _i2.LostDataResponse {
+}
+
+/// A class which mocks [ImagePickerPlatform].
+///
+/// See the documentation for Mockito's code generation for more information.
+class MockImagePickerPlatform extends _i1.Mock
+    implements _i3.ImagePickerPlatform {
+  MockImagePickerPlatform() {
+    _i1.throwOnMissingStub(this);
+  }
+
+  @override
+  _i4.Future<_i2.PickedFile?> pickImage(
+          {_i2.ImageSource? source,
+          double? maxWidth,
+          double? maxHeight,
+          int? imageQuality,
+          _i2.CameraDevice? preferredCameraDevice = _i2.CameraDevice.rear}) =>
+      (super.noSuchMethod(
+              Invocation.method(#pickImage, [], {
+                #source: source,
+                #maxWidth: maxWidth,
+                #maxHeight: maxHeight,
+                #imageQuality: imageQuality,
+                #preferredCameraDevice: preferredCameraDevice
+              }),
+              returnValue: Future<_i2.PickedFile?>.value())
+          as _i4.Future<_i2.PickedFile?>);
+  @override
+  _i4.Future<List<_i2.PickedFile>?> pickMultiImage(
+          {double? maxWidth, double? maxHeight, int? imageQuality}) =>
+      (super.noSuchMethod(
+              Invocation.method(#pickMultiImage, [], {
+                #maxWidth: maxWidth,
+                #maxHeight: maxHeight,
+                #imageQuality: imageQuality
+              }),
+              returnValue: Future<List<_i2.PickedFile>?>.value())
+          as _i4.Future<List<_i2.PickedFile>?>);
+  @override
+  _i4.Future<_i2.PickedFile?> pickVideo(
+          {_i2.ImageSource? source,
+          _i2.CameraDevice? preferredCameraDevice = _i2.CameraDevice.rear,
+          Duration? maxDuration}) =>
+      (super.noSuchMethod(
+              Invocation.method(#pickVideo, [], {
+                #source: source,
+                #preferredCameraDevice: preferredCameraDevice,
+                #maxDuration: maxDuration
+              }),
+              returnValue: Future<_i2.PickedFile?>.value())
+          as _i4.Future<_i2.PickedFile?>);
+  @override
+  _i4.Future<_i2.LostData> retrieveLostData() =>
+      (super.noSuchMethod(Invocation.method(#retrieveLostData, []),
+              returnValue: Future<_i2.LostData>.value(_FakeLostData_0()))
+          as _i4.Future<_i2.LostData>);
+  @override
+  _i4.Future<_i5.XFile?> getImage(
+          {_i2.ImageSource? source,
+          double? maxWidth,
+          double? maxHeight,
+          int? imageQuality,
+          _i2.CameraDevice? preferredCameraDevice = _i2.CameraDevice.rear}) =>
+      (super.noSuchMethod(
+          Invocation.method(#getImage, [], {
+            #source: source,
+            #maxWidth: maxWidth,
+            #maxHeight: maxHeight,
+            #imageQuality: imageQuality,
+            #preferredCameraDevice: preferredCameraDevice
+          }),
+          returnValue: Future<_i5.XFile?>.value()) as _i4.Future<_i5.XFile?>);
+  @override
+  _i4.Future<List<_i5.XFile>?> getMultiImage(
+          {double? maxWidth, double? maxHeight, int? imageQuality}) =>
+      (super.noSuchMethod(
+              Invocation.method(#getMultiImage, [], {
+                #maxWidth: maxWidth,
+                #maxHeight: maxHeight,
+                #imageQuality: imageQuality
+              }),
+              returnValue: Future<List<_i5.XFile>?>.value())
+          as _i4.Future<List<_i5.XFile>?>);
+  @override
+  _i4.Future<_i5.XFile?> getVideo(
+          {_i2.ImageSource? source,
+          _i2.CameraDevice? preferredCameraDevice = _i2.CameraDevice.rear,
+          Duration? maxDuration}) =>
+      (super.noSuchMethod(
+          Invocation.method(#getVideo, [], {
+            #source: source,
+            #preferredCameraDevice: preferredCameraDevice,
+            #maxDuration: maxDuration
+          }),
+          returnValue: Future<_i5.XFile?>.value()) as _i4.Future<_i5.XFile?>);
+  @override
+  _i4.Future<_i2.LostDataResponse> getLostData() =>
+      (super.noSuchMethod(Invocation.method(#getLostData, []),
+              returnValue:
+                  Future<_i2.LostDataResponse>.value(_FakeLostDataResponse_1()))
+          as _i4.Future<_i2.LostDataResponse>);
+  @override
+  _i4.Future<_i5.XFile?> getImageFromSource(
+          {_i2.ImageSource? source,
+          _i2.ImagePickerOptions? options = const _i2.ImagePickerOptions()}) =>
+      (super.noSuchMethod(
+          Invocation.method(
+              #getImageFromSource, [], {#source: source, #options: options}),
+          returnValue: Future<_i5.XFile?>.value()) as _i4.Future<_i5.XFile?>);
+}