Fix a couple test timeouts.

R=rnystrom@google.com

Review URL: https://codereview.chromium.org//864983002
diff --git a/test/server/batch_test.dart b/test/server/batch_test.dart
index 7dda84f..f92a3cf 100644
--- a/test/server/batch_test.dart
+++ b/test/server/batch_test.dart
@@ -70,7 +70,7 @@
       {'jsonrpc': '2.0', 'method': 'foo'},
       {'jsonrpc': '2.0', 'method': 'id', 'params': ['value']},
       {'jsonrpc': '2.0', 'method': 'arg', 'params': {'arg': 'value'}}
-    ]), completion(isNull));
+    ]), doesNotComplete);
   });
 
   test('returns an error if the batch is empty', () {
diff --git a/test/server/server_test.dart b/test/server/server_test.dart
index a89a0d9..10498b7 100644
--- a/test/server/server_test.dart
+++ b/test/server/server_test.dart
@@ -89,7 +89,7 @@
       'jsonrpc': '2.0',
       'method': 'foo',
       'params': {}
-    }), completion(isNull));
+    }), doesNotComplete);
   });
 
   test("includes the error data in the response", () {
diff --git a/test/server/utils.dart b/test/server/utils.dart
index a4fd36a..75dc9b2 100644
--- a/test/server/utils.dart
+++ b/test/server/utils.dart
@@ -61,6 +61,20 @@
   })));
 }
 
+/// Returns a matcher that matches [Future]s that never complete.
+Matcher get doesNotComplete => predicate((future) {
+  future.then(expectAsync((_) {
+    // This will never be called. [expectAsync] with `count: 0` ensures that an
+    // error will be thrown when [future] completes.
+  }, count: 0));
+
+  // Make sure there's enough time in the test for [expectAsync] to fail if it's
+  // going to.
+  expect(pumpEventQueue(), completes);
+
+  return true;
+});
+
 /// Returns a matcher that matches a [json_rpc.RpcException] with an
 /// `invalid_params` error code.
 Matcher throwsInvalidParams(String message) {