Mockito codegen: use fallbackGenerator when present to create a default 'returnValueForMissingStub'.

When running in sound mode, this allows overriding the default missingStub implementation that might fail at runtime (generics for ex.).

PiperOrigin-RevId: 472925798
diff --git a/lib/src/builder.dart b/lib/src/builder.dart
index a70d830..2935c43 100644
--- a/lib/src/builder.dart
+++ b/lib/src/builder.dart
@@ -1350,9 +1350,15 @@
       returnValueForMissingStub =
           _futureReference(refer('void')).property('value').call([]);
     } else if (mockTarget.onMissingStub == OnMissingStub.returnDefault) {
-      // Return a legal default value if no stub is found which matches a real
-      // call.
-      returnValueForMissingStub = _dummyValue(returnType, invocation);
+      if (fallbackGenerator != null) {
+        // Re-use the fallback for missing stub.
+        returnValueForMissingStub =
+            _fallbackGeneratorCode(method, fallbackGenerator);
+      } else {
+        // Return a legal default value if no stub is found which matches a real
+        // call.
+        returnValueForMissingStub = _dummyValue(returnType, invocation);
+      }
     }
     final namedArgs = {
       if (fallbackGenerator != null)
@@ -1819,7 +1825,9 @@
       else if (typeSystem._returnTypeIsNonNullable(getter))
         'returnValue': _dummyValue(returnType, invocation),
       if (mockTarget.onMissingStub == OnMissingStub.returnDefault)
-        'returnValueForMissingStub': _dummyValue(returnType, invocation),
+        'returnValueForMissingStub': (fallbackGenerator != null
+            ? _fallbackGeneratorCode(getter, fallbackGenerator)
+            : _dummyValue(returnType, invocation)),
     };
     var superNoSuchMethod =
         refer('super').property('noSuchMethod').call([invocation], namedArgs);
diff --git a/test/builder/custom_mocks_test.dart b/test/builder/custom_mocks_test.dart
index 0a5ab48..3d653a3 100644
--- a/test/builder/custom_mocks_test.dart
+++ b/test/builder/custom_mocks_test.dart
@@ -936,6 +936,39 @@
   });
 
   test(
+      'generates mock classes including a fallback generator and '
+      'OnMissingStub.returnDefault', () async {
+    var mocksContent = await buildWithNonNullable({
+      ...annotationsAsset,
+      'foo|lib/foo.dart': dedent(r'''
+        abstract class Foo<T> {
+          T get f;
+        }
+        '''),
+      'foo|test/foo_test.dart': '''
+        import 'package:foo/foo.dart';
+        import 'package:mockito/annotations.dart';
+
+        T fShim<T>() {
+          throw 'unknown';
+        }
+
+        @GenerateMocks(
+          [],
+          customMocks: [
+            MockSpec<Foo>(
+                fallbackGenerators: {#f: fShim},
+                onMissingStub: OnMissingStub.returnDefault),
+          ],
+        )
+        void main() {}
+        '''
+    });
+    expect(mocksContent, contains('returnValue: _i3.fShim(),'));
+    expect(mocksContent, contains('returnValueForMissingStub: _i3.fShim(),'));
+  });
+
+  test(
       'throws when GenerateMocks is given a class with a type parameter with a '
       'private bound', () async {
     _expectBuilderThrows(
@@ -1265,7 +1298,36 @@
         '''
     });
     expect(mocksContent, isNot(contains('throwOnMissingStub')));
-    expect(mocksContent, contains('returnValueForMissingStub:'));
+    expect(mocksContent, contains('returnValue: 0'));
+    expect(mocksContent, contains('returnValueForMissingStub: 0'));
+  });
+
+  test(
+      'generates a mock class which uses the new behavior of returning '
+      'a valid value for missing stubs, if GenerateNiceMocks and '
+      'fallbackGenerators were used', () async {
+    var mocksContent = await buildWithNonNullable({
+      ...annotationsAsset,
+      'foo|lib/foo.dart': dedent(r'''
+        class Foo<T> {
+          int m();
+        }
+        '''),
+      'foo|test/foo_test.dart': '''
+        import 'package:foo/foo.dart';
+        import 'package:mockito/annotations.dart';
+
+        int mShim() {
+          return 1;
+        }
+
+        @GenerateNiceMocks([MockSpec<Foo>(fallbackGenerators: {#m: mShim})])
+        void main() {}
+        '''
+    });
+    expect(mocksContent, isNot(contains('throwOnMissingStub')));
+    expect(mocksContent, contains('returnValue: _i3.mShim(),'));
+    expect(mocksContent, contains('returnValueForMissingStub: _i3.mShim(),'));
   });
 
   test('mixed GenerateMocks and GenerateNiceMocks annotations could be used',