Generate valid functions with optional non-nullable arguments
If a method of a mocked class returns a function with optional
yet non-nullable argument, Mockito currently produces something
like
```dart
(int x, {int y}) => /* doesn't matter */
```
which is not a valid Dart, since `y` must either be `required` or
have a default value. `required` won't fit into the desired type
and coming up with a default value is not easy, since it has to
be a constant, but `dummyValue` doesn't always produce one.
Fortunately, we can just widen the type here and make it nullable.
PiperOrigin-RevId: 582669927
diff --git a/lib/src/builder.dart b/lib/src/builder.dart
index 4e81787..f12e673 100644
--- a/lib/src/builder.dart
+++ b/lib/src/builder.dart
@@ -1580,12 +1580,13 @@
} else if (parameter.isOptionalPositional) {
final matchingParameter = _matchingParameter(parameter,
superParameterType: parameter.type,
- defaultName: '__p$position');
+ defaultName: '__p$position',
+ forceNullable: true);
b.optionalParameters.add(matchingParameter);
position++;
} else if (parameter.isOptionalNamed) {
final matchingParameter = _matchingParameter(parameter,
- superParameterType: parameter.type);
+ superParameterType: parameter.type, forceNullable: true);
b.optionalParameters.add(matchingParameter);
} else if (parameter.isRequiredNamed) {
final matchingParameter = _matchingParameter(parameter,
diff --git a/test/builder/auto_mocks_test.dart b/test/builder/auto_mocks_test.dart
index 34e218b..5840c9a 100644
--- a/test/builder/auto_mocks_test.dart
+++ b/test/builder/auto_mocks_test.dart
@@ -2414,7 +2414,7 @@
_containsAllOf('''
returnValue: (
int __p0, [
- String __p1,
+ String? __p1,
]) {},'''),
);
});
@@ -2431,7 +2431,7 @@
_containsAllOf('''
returnValue: (
_i2.Foo __p0, {
- bool b,
+ bool? b,
}) {},'''),
);
});
diff --git a/test/end2end/foo.dart b/test/end2end/foo.dart
index d4e26ca..46bd60f 100644
--- a/test/end2end/foo.dart
+++ b/test/end2end/foo.dart
@@ -22,6 +22,9 @@
Future<void>? returnsNullableFutureVoid() => Future.value();
Future<T> returnsFuture(T x) => Future.value(x);
Bar returnsBar(int arg) => Bar();
+ String Function(int x, [String s]) returnsFunction() => (x, [s = '']) => '';
+ String Function(int x, {String s}) returnsFunctionNamed() =>
+ (x, {s = ''}) => '';
}
class Bar {
diff --git a/test/end2end/generated_mocks_test.dart b/test/end2end/generated_mocks_test.dart
index ea1fddd..51d1967 100644
--- a/test/end2end/generated_mocks_test.dart
+++ b/test/end2end/generated_mocks_test.dart
@@ -163,6 +163,22 @@
when(foo.returnsFuture(any)).thenAnswer((_) async => 1);
expect(await foo.returnsFuture(0), 1);
});
+
+ test(
+ 'a method returning a function with optional non-nullable argument '
+ 'can be stubbed', () {
+ when(foo.returnsFunction()).thenReturn((x, [s = 'x']) => s + s);
+ expect(foo.returnsFunction()(1), equals('xx'));
+ expect(foo.returnsFunction()(1, 'y'), equals('yy'));
+ });
+
+ test(
+ 'a method returning a function with named optional non-nullable '
+ 'argument can be stubbed', () {
+ when(foo.returnsFunctionNamed()).thenReturn((x, {s = 'x'}) => s + s);
+ expect(foo.returnsFunctionNamed()(1), equals('xx'));
+ expect(foo.returnsFunctionNamed()(1, s: 'y'), equals('yy'));
+ });
});
group('for a generated mock using unsupportedMembers', () {