Add type annotations to Future dummy return values.

These allow the `as` cast to succeed; otherwise it is guaranteed to fail.

Fixes https://github.com/dart-lang/mockito/issues/380

PiperOrigin-RevId: 367907501
diff --git a/CHANGELOG.md b/CHANGELOG.md
index d490d9a..0d7afb4 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,10 @@
+## 5.0.4
+
+* Allow calling methods with void return types w/o stubbing.
+  [#367](https://github.com/dart-lang/mockito/issues/367)
+* Add type argument to dummy `Future` return value.
+  [#380](https://github.com/dart-lang/mockito/issues/380)
+
 ## 5.0.3
 
 * Support 1.x releases of source_gen.
diff --git a/lib/src/builder.dart b/lib/src/builder.dart
index 47a8dd0..0f7da31 100644
--- a/lib/src/builder.dart
+++ b/lib/src/builder.dart
@@ -872,7 +872,7 @@
     if (method.returnType.isVoid) {
       returnValueForMissingStub = refer('null');
     } else if (method.returnType.isFutureOfVoid) {
-      returnValueForMissingStub = refer('Future').property('value').call([]);
+      returnValueForMissingStub = _futureReference().property('value').call([]);
     }
     final namedArgs = {
       if (_returnTypeIsNonNullable(method))
@@ -912,7 +912,7 @@
     } else if (interfaceType.isDartAsyncFuture ||
         interfaceType.isDartAsyncFutureOr) {
       var typeArgument = typeArguments.first;
-      return refer('Future')
+      return _futureReference(_typeReference(typeArgument))
           .property('value')
           .call([_dummyValue(typeArgument)]);
     } else if (interfaceType.isDartCoreInt) {
@@ -952,6 +952,15 @@
     return _dummyValueImplementing(type as analyzer.InterfaceType);
   }
 
+  /// Returns a reference to [Future], optionally with a type argument for the
+  /// value of the Future.
+  TypeReference _futureReference([Reference valueType]) => TypeReference((b) {
+        b.symbol = 'Future';
+        if (valueType != null) {
+          b.types.add(valueType);
+        }
+      });
+
   Expression _dummyFunctionValue(analyzer.FunctionType type) {
     return Method((b) {
       // The positional parameters in a FunctionType have no names. This
diff --git a/lib/src/version.dart b/lib/src/version.dart
index 977890f..2c9f52f 100644
--- a/lib/src/version.dart
+++ b/lib/src/version.dart
@@ -1 +1 @@
-const packageVersion = '5.0.3';
+const packageVersion = '5.0.4';
diff --git a/pubspec.yaml b/pubspec.yaml
index dff34bf..543d0b6 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,5 +1,5 @@
 name: mockito
-version: 5.0.3
+version: 5.0.4
 
 description: A mock framework inspired by Mockito.
 homepage: https://github.com/dart-lang/mockito
diff --git a/test/builder/auto_mocks_test.dart b/test/builder/auto_mocks_test.dart
index d69317d..e1e53f4 100644
--- a/test/builder/auto_mocks_test.dart
+++ b/test/builder/auto_mocks_test.dart
@@ -524,7 +524,7 @@
       '''),
       _containsAllOf(dedent2('''
       _i3.Future<void> m() => (super.noSuchMethod(Invocation.method(#m, []),
-          returnValue: Future.value(null),
+          returnValue: Future<void>.value(null),
           returnValueForMissingStub: Future.value()) as _i3.Future<void>);
       ''')),
     );
@@ -1779,7 +1779,25 @@
       '''),
       _containsAllOf(dedent2('''
       _i3.Future<bool> m() => (super.noSuchMethod(Invocation.method(#m, []),
-          returnValue: Future.value(false)) as _i3.Future<bool>);
+          returnValue: Future<bool>.value(false)) as _i3.Future<bool>);
+      ''')),
+    );
+  });
+
+  test(
+      'creates dummy non-null return values for Futures of known generic core classes',
+      () async {
+    await expectSingleNonNullableOutput(
+      dedent(r'''
+      class Foo {
+        Future<Iterable<bool>> m() async => false;
+      }
+      '''),
+      _containsAllOf(dedent2('''
+      _i3.Future<Iterable<bool>> m() =>
+          (super.noSuchMethod(Invocation.method(#m, []),
+                  returnValue: Future<Iterable<bool>>.value([]))
+              as _i3.Future<Iterable<bool>>);
       ''')),
     );
   });