如何在 Dart 中统一测试异常?

考虑一个基于传递的参数进行异常处理的函数:

List range(start, stop) {
if (start >= stop) {
throw new ArgumentError("start must be less than stop");
}
// remainder of function
}

如何测试是否引发了正确类型的异常?

22125 次浏览

在这种情况下,有多种方法可以测试异常:

expect(() => range(5, 5), throwsException);

测试是否引发了正确类型的异常:

有几个预定义的匹配器用于通用目的,如 throwsArgumentErrorthrowsRangeErrorthrowsUnsupportedError等。对于不存在预定义匹配器的类型,可以使用 TypeMatcher<T>

expect(() => range(5, 2), throwsA(TypeMatcher<IndexError>()));

确保没有例外情况:

expect(() => range(5, 10), returnsNormally);

测试异常类型和异常消息:

expect(() => range(5, 3),
throwsA(predicate((e) => e is ArgumentError && e.message == 'start must be less than stop')));

还有另一种方法:

expect(() => range(5, 3),
throwsA(allOf(isArgumentError, predicate((e) => e.message == 'start must be less than stop'))));

(感谢谷歌的 Graham Wheeler 提供的最后两个解决方案)。

我喜欢这种方法:

test('when start > stop', () {
try {
range(5, 3);
} on ArgumentError catch(e) {
expect(e.message, 'start must be less than stop');
return;
}
throw new ExpectException("Expected ArgumentError");
});

对于简单的异常测试,我更喜欢使用静态方法 API:

Expect.throws(
// test condition
(){
throw new Exception('code I expect to throw');
},
// exception object inspection
(err) => err is Exception
);

使用 throwsATypeMatcher检查异常。

注意 : 现在不推荐使用 IsInstanceOf

List range(start, stop) {
if (start >= stop) {
throw new ArgumentError("start must be less than stop");
}
// remainder of function
}




test("check argument error", () {
expect(() => range(1, 2), throwsA(TypeMatcher<ArgumentError>()));
});

作为 @ Shailen Tuli提议的一个更优雅的解决方案,如果您希望在特定消息中出现错误,可以使用 having

在这种情况下,您正在寻找这样的东西:

expect(
() => range(5, 3),
throwsA(
isA<ArgumentError>().having(
(error) => error.message,        // The feature you want to check.
'message',                       // The description of the feature.
'start must be less than stop',  // The error message.
),
),
);

我使用了以下方法:

首先,您需要将方法作为 lambda 传递给 Expect 函数:

expect(() => method(...), ...)

其次,你需要结合使用 throwsAisInstanceOf

throwsA确保抛出了异常,使用 isInstanceOf可以检查是否抛出了正确的异常。

我的单元测试示例:

expect(() => parser.parse(raw), throwsA(isInstanceOf<FailedCRCCheck>()));

希望这个能帮上忙。

虽然其他的答案肯定是有效的,但是像 TypeMatcher<Type>()这样的 API 现在已经不推荐使用了,您必须使用 isA<TypeOfException>()

比如说以前,

expect(() => range(5, 2), throwsA(TypeMatcher<IndexError>()));

现在是了

expect(() => range(5, 2), throwsA(isA<IndexError>()));