Override `SmartFake.toString` to be super-verbose

Ideally I'd like it to throw, but I found that some tests use
these fakes as throw-away values: they got rendered in some HTML
or logged somewhere but never checked by the test.

Changing `toString` to throw forces such tests to add meaningless
expectations, which makes tests less readable.

So instead of throwing I decided to make `toString` just convey
the same amount of information that the exception has. This way
if the test doesn't care about the value, it will keep passing.
And if it does care, test failure will contain useful information,
suggesting what needs to be stubbed.

PiperOrigin-RevId: 494732315
diff --git a/lib/src/mock.dart b/lib/src/mock.dart
index 4b2c9e9..f4b52d2 100644
--- a/lib/src/mock.dart
+++ b/lib/src/mock.dart
@@ -228,6 +228,7 @@
   final Object _parent;
   final Invocation _parentInvocation;
   final StackTrace _createdStackTrace;
+  late final StackTrace _toStringFirstCalled = StackTrace.current;
 
   // Override [Object.operator==] to accept `Object?`. This is needed to
   // make Analyzer happy, if we fake classes that override `==` to
@@ -240,6 +241,26 @@
       _parentInvocation, invocation, _parent, _createdStackTrace);
   SmartFake(this._parent, this._parentInvocation)
       : _createdStackTrace = StackTrace.current;
+
+  @override
+  String toString() {
+    final memberName = _symbolToString(_parentInvocation.memberName);
+    return '''Fake object created as a result of calling unstubbed member
+$memberName of a mock.
+
+Here is the stack trace where $memberName was called:
+
+$_createdStackTrace
+
+Normally you would never see this message, if it breaks your test,
+consider adding a stub for ${_parent.runtimeType}.$memberName using Mockito's
+'when' API.
+
+Here is the stack trace where toString() was first called:
+
+$_toStringFirstCalled
+''';
+  }
 }
 
 class FakeUsedError extends Error {