try {
await methodWhichThrows();
fail("exception not thrown");
} catch (e) {
expect(e, new isInstanceOf<...>());
// more expect statements can go here
}
这种方法还有一个优点,即可以对异常的值执行额外的检查。
Expect with throwsA仅用作最后一条语句
仅当 expect 是测试中的最后一条语句时,单独使用 expect 才有效。无法控制 when 方法将抛出异常,因此,如果假设异常已经被抛出,则语句(包括对 expect 的后续调用)可能存在争用条件。
expect(methodWhichThrows(), throwsA(new isInstanceOf<...>())); // unreliable unless last
import 'dart:async';
import 'package:test/test.dart';
//----------------------------------------------------------------
/// This approach to expecting exceptions is reliable.
///
Future reliableApproach(int luck) async {
expect(await setValueAndReturnsHalf(42), equals(21));
expect(state, equals(Evenness.isEven));
try {
await setValueAndReturnsHalf(3);
fail("exception not thrown");
} catch (e) {
expect(e, new isInstanceOf<ArgumentError>());
}
// Expect value to be odd after execption is thrown.
await shortDelay(luck); // in my experience there's no such thing called luck
expect(state, equals(Evenness.isOdd));
}
//----------------------------------------------------------------
/// This approach to expecting exceptions is unreliable.
///
Future unreliableApproach(int luck) async {
expect(await setValueAndReturnsHalf(42), equals(21));
expect(state, equals(Evenness.isEven));
expect(setValueAndReturnsHalf(3), throwsA(new isInstanceOf<ArgumentError>()));
// Expect value to be odd after execption is thrown.
await shortDelay(luck); // luck determines if the race condition is triggered
expect(state, equals(Evenness.isOdd));
}
//----------------------------------------------------------------
enum Evenness { isEven, isOdd, inLimbo }
int value = 0;
Evenness state = Evenness.isEven;
/// Sets the [value] and [state].
///
/// If the [newValue] is even, [state] is set to [Evenness.isEven] and half of it
/// is returned as the Future's value.
///
/// If the [newValue] is odd, [state] is set to [Evenness.isOdd] and an exception
/// is thrown.
///
/// To simulate race conditions, this method takes 2 seconds before it starts
/// processing and 4 seconds to succeed or throw an exception. While it is
/// processing, the [state] is set to [Evenness.inLimbo].
///
Future<int> setValueAndReturnsHalf(int newValue) async {
await shortDelay(2);
state = Evenness.inLimbo;
await shortDelay(2);
value = newValue;
if (newValue % 2 != 0) {
state = Evenness.isOdd;
throw new ArgumentError.value(newValue, "value", "is not an even number");
} else {
state = Evenness.isEven;
return value ~/ 2;
}
}
/// Delays used to simulate processing and race conditions.
///
Future shortDelay(int seconds) {
var c = new Completer();
new Timer(new Duration(seconds: seconds), () => c.complete());
return c.future;
}
/// Examples of the reliable and unreliable approaches.
///
void main() {
test("Correct operation when exception is not thrown", () async {
expect(await setValueAndReturnsHalf(42), equals(21));
expect(value, equals(42));
});
group("Reliable approach:", () {
test("works when there is bad luck", () async {
// 1 second = bad luck, future returning function not started processing yet
await reliableApproach(1);
});
test("works when there is more bad luck", () async {
// 3 second = bad luck, future returning function still processing
await reliableApproach(3);
});
test("works when there is good luck", () async {
// 5 seconds = good luck, future returning function definitely finished
await reliableApproach(5);
});
});
group("Unreliable approach:", () {
test("race condition encountered by bad luck", () async {
// 1 second = bad luck, future returning function not started processing yet
await unreliableApproach(1);
});
test("race condition encountered by more bad luck", () async {
// 3 second = bad luck, future returning function still processing
await unreliableApproach(3);
});
test("race condition avoided by good luck", () async {
// 5 seconds = good luck, future returning function definitely finished
await unreliableApproach(5);
});
});
}
test('ArgumentError is thrown when throwIt is true', () {
expectLater(() => myAsyncFunctionThatTakesAnArgument(throwIt: true), throwsA(isA<ArgumentError>()));
});
7条答案
按热度按时间nfeuvbwi1#
使用试接
最可靠的方法是使用一个 try-catch 块来显式捕获异常,并确保方法已经完成运行。
这种方法还有一个优点,即可以对异常的值执行额外的检查。
Expect with throwsA仅用作最后一条语句
仅当 expect 是测试中的最后一条语句时,单独使用 expect 才有效。无法控制 when 方法将抛出异常,因此,如果假设异常已经被抛出,则语句(包括对 expect 的后续调用)可能存在争用条件。
它是可以使用的,但你必须非常小心地记住它在哪些情况下有效,哪些情况下无效。所以坚持使用 try-catch 方法比在不同的情况下使用不同的方法更安全。
示范
下面的完整示例演示争用条件对这两种方法的影响:
pdkcd3nj2#
它是这样工作的:
基本上只需要删除
await
。测试框架可以处理future,无论它们是成功还是失败。a0zr77ik3#
official document有很好的例子,使用
expectLater
和throwsA
,如下所示。wr98u20j4#
最简单、最简短的答案是:
要测试异常/错误类型:
wyyhbhjk5#
有多种方法可以测试来自Future的错误。如果“throws without async”方法抛出一些异常,Gunter的答案将起作用。下面的示例将处理来自Future方法的异常。
afdcj2ne6#
经过太多的尝试和错误,我发现这一个工作如预期:
6qfn3psc7#
我不满意其他人的回答太冗长了。
简单来说就是: