Use the new test_api package, checking for version incompatibility (#176)

Bump to 4.0.0, using the new test_api package
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 1bc586e..7548459 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,13 @@
+## 4.0.0
+
+* Replace the dependency on the
+  _[test](https://pub.dartlang.org/packages/test)_ package with a dependency on
+  the new _[test_api](https://pub.dartlang.org/packages/test_api)_ package.
+  This dramatically reduces mockito's transitive dependencies.
+
+  This bump can result in runtime errors when coupled with a version of the
+  test package older than 1.4.0.
+
 ## 3.0.2
 
 * Rollback the _[test_api](https://pub.dartlang.org/packages/test_api)_ part of
diff --git a/lib/src/mock.dart b/lib/src/mock.dart
index 7601072..7df111a 100644
--- a/lib/src/mock.dart
+++ b/lib/src/mock.dart
@@ -17,7 +17,11 @@
 import 'package:meta/meta.dart';
 import 'package:mockito/src/call_pair.dart';
 import 'package:mockito/src/invocation_matcher.dart';
-import 'package:test/test.dart';
+import 'package:test_api/test_api.dart';
+// TODO(srawlins): Remove this when we no longer need to check for an
+// incompatiblity between test_api and test.
+// https://github.com/dart-lang/mockito/issues/175
+import 'package:test_api/src/backend/invoker.dart';
 
 bool _whenInProgress = false;
 bool _untilCalledInProgress = false;
@@ -659,12 +663,55 @@
   List<dynamic> captured = [];
   int callCount;
 
+  // Whether the test API mismatch has been checked.
+  bool _testApiMismatchHasBeenChecked = false;
+
   VerificationResult(this.callCount) {
     captured = new List<dynamic>.from(_capturedArgs, growable: false);
     _capturedArgs.clear();
   }
 
+  /// Check for a version incompatibility between mockito, test, and test_api.
+  ///
+  /// This incompatibility results in an inscrutible error for users. Catching
+  /// it here allows us to give some steps to fix.
+  // TODO(srawlins): Remove this when we don't need to check for an
+  // incompatiblity between test_api and test any more.
+  // https://github.com/dart-lang/mockito/issues/175
+  void _checkTestApiMismatch() {
+    try {
+      Invoker.current;
+    } on CastError catch (e) {
+      if (!e
+          .toString()
+          .contains("type 'Invoker' is not a subtype of type 'Invoker'")) {
+        // Hmm. This is a different CastError from the one we're trying to
+        // protect against. Let it go.
+        return;
+      }
+      print('Error: Package incompatibility between mockito, test, and '
+          'test_api packages:');
+      print('');
+      print('* mockito ^4.0.0 is incompatible with test <1.4.0');
+      print('* mockito <4.0.0 is incompatible with test ^1.4.0');
+      print('');
+      print('As mockito does not have a dependency on the test package, '
+          'nothing stopped you from landing in this situation. :( '
+          'Apologies.');
+      print('');
+      print('To fix: bump your dependency on the test package to something '
+          'like: ^1.4.0');
+      rethrow;
+    }
+  }
+
   void called(matcher) {
+    if (!_testApiMismatchHasBeenChecked) {
+      // Only execute the check below once. `Invoker.current` may look like a
+      // cheap getter, but it involves Zones and casting.
+      _testApiMismatchHasBeenChecked = true;
+      _checkTestApiMismatch();
+    }
     expect(callCount, wrapMatcher(matcher),
         reason: "Unexpected number of calls");
   }
diff --git a/pubspec.yaml b/pubspec.yaml
index 768857e..bcb809c 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,5 +1,5 @@
 name: mockito
-version: 3.0.2
+version: 4.0.0
 
 authors:
   - Dmitriy Fibulwinter <fibulwinter@gmail.com>
@@ -15,10 +15,11 @@
   collection: ^1.1.0
   matcher: ^0.12.3
   meta: ^1.0.4
-  test: ^1.2.0
+  test_api: ^0.2.1
 
 dev_dependencies:
   build_runner: ^1.0.0
   build_test: ^0.10.0
   build_web_compilers: ^0.4.0
   pedantic: ^1.3.0
+  test: ^1.5.1