Add a Fake class with a throwing noSuchMethod (#191)

Closes #169

Adds a slightly better pattern for current abuses of the `Mock` class
when it is used only to avoid implementing an entire interface rather
than for it's actual mocking capabilities.
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 7548459..9d1e31a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,8 @@
+## 4.1.0
+
+* Add a `Fake` class for implementing a subset of a class API as overrides
+  without misusing the `Mock` class.
+
 ## 4.0.0
 
 * Replace the dependency on the
diff --git a/lib/mockito.dart b/lib/mockito.dart
index 046f68c..87da9da 100644
--- a/lib/mockito.dart
+++ b/lib/mockito.dart
@@ -14,6 +14,7 @@
 
 export 'src/mock.dart'
     show
+        Fake,
         Mock,
         named,
 
diff --git a/lib/src/mock.dart b/lib/src/mock.dart
index 9672cc6..2d43a95 100644
--- a/lib/src/mock.dart
+++ b/lib/src/mock.dart
@@ -74,6 +74,11 @@
 ///       print(cat.getSound('foo')); // Prints 'Woof'
 ///     }
 ///
+/// A class which `extends Mock` should not have any directly implemented
+/// overridden fields or methods. These fields would not be usable as a [Mock]
+/// with [verify] or [when]. To implement a subset of an interface manually use
+/// [Fake] instead.
+///
 /// **WARNING**: [Mock] uses [noSuchMethod](goo.gl/r3IQUH), which is a _form_ of
 /// runtime reflection, and causes sub-standard code to be generated. As such,
 /// [Mock] should strictly _not_ be used in any production code, especially if
@@ -152,6 +157,54 @@
   }
 }
 
+/// Extend or mixin this class to mark the implementation as a [Fake].
+///
+/// A fake has a default behavior for every field and method of throwing
+/// [UnimplementedError]. Fields and methods that are excersized by the code
+/// under test should be manually overridden in the implementing class.
+///
+/// A fake does not have any support for verification or defining behavior from
+/// the test, it cannot be used as a [Mock].
+///
+/// In most cases a shared full fake implementation without a `noSuchMethod` is
+/// preferable to `extends Fake`, however `extends Fake` is preferred against
+/// `extends Mock` mixed with manual `@override` implementations.
+///
+/// __Example use__:
+///
+///     // Real class.
+///     class Cat {
+///       String meow(String suffix) => 'Meow$suffix';
+///       String hiss(String suffix) => 'Hiss$suffix';
+///     }
+///
+///     // Fake class.
+///     class FakeCat extends Fake implements Cat {
+///       @override
+///       String meow(String suffix) => 'FakeMeow$suffix';
+///     }
+///
+///     void main() {
+///       // Create a new fake Cat at runtime.
+///       var cat = new FakeCat();
+///
+///       // Try making a Cat sound...
+///       print(cat.meow('foo')); // Prints 'FakeMeowfoo'
+///       print(cat.hiss('foo')); // Throws
+///     }
+///
+/// **WARNING**: [Fake] uses [noSuchMethod](goo.gl/r3IQUH), which is a _form_ of
+/// runtime reflection, and causes sub-standard code to be generated. As such,
+/// [Fake] 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).
+abstract class Fake {
+  @override
+  dynamic noSuchMethod(Invocation invocation) {
+    throw UnimplementedError(invocation.memberName.toString().split('"')[1]);
+  }
+}
+
 typedef _ReturnsCannedResponse = CallPair<dynamic> Function();
 
 // When using an [ArgMatcher], we transform our invocation to have knowledge of
diff --git a/pubspec.yaml b/pubspec.yaml
index 8903ae8..3570b41 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,5 +1,5 @@
 name: mockito
-version: 4.0.0
+version: 4.1.0
 
 authors:
   - Dmitriy Fibulwinter <fibulwinter@gmail.com>