mirror of
https://github.com/dart-lang/sdk
synced 2024-11-02 06:20:13 +00:00
Add asyncExpectThrows<T>() to async_helper.
This lets you test that a callback returns a Future that completes to a given error. Like Expect.throws(), but async. At first, I added support for this directly to Expect.throws(), but I think it's better to minimize the amount of dynamic logic going on in the language test framework. I was worried about having to duplicate all of the Expect.throws___() convenience functions but now that we have generic methods, those functions aren't that much more convenient. Change-Id: I8b288945611fa16f8d27056f3cf79181fc22d256 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/97881 Reviewed-by: William Hesse <whesse@google.com>
This commit is contained in:
parent
994f535e03
commit
ffee99d79b
2 changed files with 72 additions and 16 deletions
|
@ -25,6 +25,8 @@ library async_helper;
|
|||
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:expect/expect.dart';
|
||||
|
||||
bool _initialized = false;
|
||||
int _asyncLevel = 0;
|
||||
|
||||
|
@ -87,3 +89,52 @@ Future<void> asyncTest(f()) {
|
|||
asyncStart();
|
||||
return f().then(asyncSuccess);
|
||||
}
|
||||
|
||||
/// Calls [f] and verifies that it throws a `T`.
|
||||
///
|
||||
/// The optional [check] function can provide additional validation that the
|
||||
/// correct object is being thrown. For example, to check the content of the
|
||||
/// thrown object you could write this:
|
||||
///
|
||||
/// asyncExpectThrows<MyException>(myThrowingFunction,
|
||||
/// (e) => e.myMessage.contains("WARNING"));
|
||||
///
|
||||
/// If `f` fails an expectation (i.e., throws an [ExpectException]), that
|
||||
/// exception is not caught by [asyncExpectThrows]. The test is still considered
|
||||
/// failing.
|
||||
void asyncExpectThrows<T>(Future<void> f(),
|
||||
[bool check(T error), String reason]) {
|
||||
var type = "";
|
||||
if (T != dynamic && T != Object) type = "<$T>";
|
||||
var header = "asyncExpectThrows$type(${reason ?? ''}):";
|
||||
|
||||
// TODO(rnystrom): It might useful to validate that T is not bound to
|
||||
// ExpectException since that won't work.
|
||||
|
||||
if (f is! Function()) {
|
||||
// Only throws from executing the function body should count as throwing.
|
||||
// The failure to even call `f` should throw outside the try/catch.
|
||||
Expect.testError("$header Function not callable with zero arguments.");
|
||||
}
|
||||
|
||||
var result = f();
|
||||
if (result is! Future) {
|
||||
Expect.testError("$header Function did not return a Future.");
|
||||
}
|
||||
|
||||
asyncStart();
|
||||
result.then((_) {
|
||||
throw ExpectException("$header Did not throw.");
|
||||
}).catchError((error, stack) {
|
||||
// A test failure doesn't count as throwing.
|
||||
if (error is ExpectException) throw error;
|
||||
|
||||
if (error is! T || (check != null && !check(error))) {
|
||||
// Throws something unexpected.
|
||||
throw ExpectException(
|
||||
"$header Unexpected '${Error.safeToString(error)}'\n$stack");
|
||||
}
|
||||
|
||||
asyncEnd();
|
||||
});
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
// SharedOptions=--enable-experiment=control-flow-collections,spread-collections
|
||||
|
||||
import "package:async_helper/async_helper.dart";
|
||||
import 'package:async_helper/async_helper.dart';
|
||||
import 'package:expect/expect.dart';
|
||||
|
||||
import 'utils.dart';
|
||||
|
@ -250,25 +250,30 @@ Future<void> testKeyOrder() async {
|
|||
Future<void> testRuntimeErrors() async {
|
||||
// Cast variable.
|
||||
dynamic nonStream = 3;
|
||||
Expect.throwsTypeError(() => <int>[await for (int i in nonStream) 1]);
|
||||
Expect.throwsTypeError(() => <int, int>{await for (int i in nonStream) 1: 1});
|
||||
Expect.throwsTypeError(() => <int>{await for (int i in nonStream) 1});
|
||||
asyncExpectThrows<TypeError>(
|
||||
() async => <int>[await for (int i in nonStream) 1]);
|
||||
asyncExpectThrows<TypeError>(
|
||||
() async => <int, int>{await for (int i in nonStream) 1: 1});
|
||||
asyncExpectThrows<TypeError>(
|
||||
() async => <int>{await for (int i in nonStream) 1});
|
||||
|
||||
// Null stream.
|
||||
Stream<int> nullStream = null;
|
||||
Expect.throwsNoSuchMethodError(
|
||||
() => <int>[await for (var i in nullStream) 1]);
|
||||
Expect.throwsNoSuchMethodError(
|
||||
() => <int, int>{await for (var i in nullStream) 1: 1});
|
||||
Expect.throwsNoSuchMethodError(
|
||||
() => <int>{await for (var i in nullStream) 1});
|
||||
asyncExpectThrows<NoSuchMethodError>(
|
||||
() async => <int>[await for (var i in nullStream) 1]);
|
||||
asyncExpectThrows<NoSuchMethodError>(
|
||||
() async => <int, int>{await for (var i in nullStream) 1: 1});
|
||||
asyncExpectThrows<NoSuchMethodError>(
|
||||
() async => <int>{await for (var i in nullStream) 1});
|
||||
|
||||
// Wrong element type.
|
||||
dynamic nonInt = "string";
|
||||
Expect.throwsTypeError(() => <int>[await for (var i in stream([1])) nonInt]);
|
||||
Expect.throwsTypeError(
|
||||
() => <int, int>{await for (var i in stream([1])) nonInt: 1});
|
||||
Expect.throwsTypeError(
|
||||
() => <int, int>{await for (var i in stream([1])) 1: nonInt});
|
||||
Expect.throwsTypeError(() => <int>{await for (var i in stream([1])) nonInt});
|
||||
asyncExpectThrows<TypeError>(
|
||||
() async => <int>[await for (var i in stream([1])) nonInt]);
|
||||
asyncExpectThrows<TypeError>(
|
||||
() async => <int, int>{await for (var i in stream([1])) nonInt: 1});
|
||||
asyncExpectThrows<TypeError>(
|
||||
() async => <int, int>{await for (var i in stream([1])) 1: nonInt});
|
||||
asyncExpectThrows<TypeError>(
|
||||
() async => <int>{await for (var i in stream([1])) nonInt});
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue