Change default dummy value for `String` to contain some info

PiperOrigin-RevId: 571241586
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4d1dba8..b512d3a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,6 +3,10 @@
 * Require analyzer 5.12.0, allow analyzer version 6.x;
 * Add example of writing a class to mock function objects.
 * Add support for the `build_extensions` build.yaml option
+* Require Dart >= 3.0.0.
+* **Potentially breaking** Changed default `String` value returned by nice
+  mocks' unstubbed method to include some useful info. This could break the
+  tests that relied on getting an empty `String` from unstubbed methods.
 
 ## 5.4.2
 
diff --git a/lib/src/builder.dart b/lib/src/builder.dart
index 48be220..e354ed2 100644
--- a/lib/src/builder.dart
+++ b/lib/src/builder.dart
@@ -1567,8 +1567,6 @@
           ..url = 'dart:async'
           ..types.add(elementType);
       }).property('empty').call([]);
-    } else if (type.isDartCoreString) {
-      return literalString('');
     } else if (type.isDartTypedDataSealed) {
       // These types (XXXList + ByteData) from dart:typed_data are
       // sealed, e.g. "non-subtypeable", but they
diff --git a/lib/src/dummies.dart b/lib/src/dummies.dart
index f5630c1..71c77b6 100644
--- a/lib/src/dummies.dart
+++ b/lib/src/dummies.dart
@@ -16,7 +16,7 @@
 import 'dart:collection';
 import 'dart:typed_data';
 
-import 'mock.dart' show FakeFunctionUsedError;
+import 'mock.dart' show FakeFunctionUsedError, PrettyString;
 import 'platform_dummies_js.dart'
     if (dart.library.io) 'platform_dummies_vm.dart';
 
@@ -24,7 +24,11 @@
 // String could totally contain an explanation.
 const int _dummyInt = 0;
 const double _dummyDouble = 0.0;
-const String _dummyString = '';
+
+// Create a dummy String with info on why it was created.
+String _dummyString(Object o, Invocation i) => Uri.encodeComponent(
+    'Dummy String created while calling ${i.toPrettyString()} on $o.'
+        .replaceAll(' ', '_'));
 
 // This covers functions with up to 20 positional arguments, for more arguments,
 // type arguments or named arguments, users would have to provide a dummy
@@ -104,7 +108,7 @@
   int: (_, _i) => _dummyInt,
   num: (_, _i) => _dummyInt,
   double: (_, _i) => _dummyDouble,
-  String: (_, _i) => _dummyString,
+  String: _dummyString,
   Int8List: (_, _i) => Int8List(0),
   Int16List: (_, _i) => Int16List(0),
   Int32List: (_, _i) => Int32List(0),
diff --git a/lib/src/mock.dart b/lib/src/mock.dart
index f988cf1..d53b017 100644
--- a/lib/src/mock.dart
+++ b/lib/src/mock.dart
@@ -123,7 +123,7 @@
 /// be generated. As such, [Mock] should strictly _not_ be used in any
 /// production code, especially if used within the context of Dart for Web
 /// (dart2js, DDC) and Dart for Mobile (Flutter).
-class Mock {
+mixin class Mock {
   static Null _answerNull(_) => null;
 
   static const _nullResponse = CallPair<Null>.allInvocations(_answerNull);
@@ -1270,7 +1270,7 @@
   resetDummyBuilders();
 }
 
-extension on Invocation {
+extension PrettyString on Invocation {
   /// Returns a pretty String representing a method (or getter or setter) call
   /// including its arguments, separating elements with newlines when it should
   /// improve readability.
diff --git a/pubspec.yaml b/pubspec.yaml
index 6d9c556..12c2051 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -6,7 +6,7 @@
 repository: https://github.com/dart-lang/mockito
 
 environment:
-  sdk: '>=2.19.0 <4.0.0'
+  sdk: '>=3.0.0 <4.0.0'
 
 dependencies:
   analyzer: '>=5.12.0 <7.0.0'
diff --git a/test/builder/auto_mocks_test.dart b/test/builder/auto_mocks_test.dart
index 31a6244..b275cc5 100644
--- a/test/builder/auto_mocks_test.dart
+++ b/test/builder/auto_mocks_test.dart
@@ -2259,14 +2259,15 @@
     );
   });
 
-  test('creates dummy non-null String return value', () async {
+  test('calls dummyValue to get a dummy non-null String return value',
+      () async {
     await expectSingleNonNullableOutput(
       dedent(r'''
       class Foo {
         String m() => "Hello";
       }
       '''),
-      _containsAllOf("returnValue: '',"),
+      _containsAllOf('returnValue: _i3.dummyValue<String>('),
     );
   });
 
diff --git a/test/end2end/generated_mocks_test.dart b/test/end2end/generated_mocks_test.dart
index 64573f4..d081ee2 100644
--- a/test/end2end/generated_mocks_test.dart
+++ b/test/end2end/generated_mocks_test.dart
@@ -263,11 +263,19 @@
 
     test('an unstubbed method returns a value', () {
       when(foo.namedParameter(x: 42)).thenReturn('Stubbed');
-      expect(foo.namedParameter(x: 43), equals(''));
+      expect(
+          foo.namedParameter(x: 43),
+          contains(Uri.encodeComponent(
+              'Dummy String created while calling namedParameter({x: 43})'
+                  .replaceAll(' ', '_'))));
     });
 
     test('an unstubbed getter returns a value', () {
-      expect(foo.getter, equals(''));
+      expect(
+          foo.getter,
+          contains(Uri.encodeComponent(
+              'Dummy String created while calling getter'
+                  .replaceAll(' ', '_'))));
     });
   });
 
@@ -280,11 +288,19 @@
 
     test('an unstubbed method returns a value', () {
       when(foo.namedParameter(x: 42)).thenReturn('Stubbed');
-      expect(foo.namedParameter(x: 43), equals(''));
+      expect(
+          foo.namedParameter(x: 43),
+          contains(Uri.encodeComponent(
+              'Dummy String created while calling namedParameter({x: 43})'
+                  .replaceAll(' ', '_'))));
     });
 
     test('an unstubbed getter returns a value', () {
-      expect(foo.getter, equals(''));
+      expect(
+          foo.getter,
+          contains(Uri.encodeComponent(
+              'Dummy String created while calling getter'
+                  .replaceAll(' ', '_'))));
     });
 
     test('an unstubbed method returning non-core type returns a fake', () {