59

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

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

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

4

7 回答 7

135

在这种情况下,有多种方法可以测试异常。简单地测试是否引发了非特定异常:

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

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

有几个用于一般用途的预定义匹配器,例如throwsArgumentError, throwsRangeError,throwsUnsupportedError等。对于不存在预定义匹配器的类型,您可以使用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'))));

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

于 2012-11-08T22:33:34.053 回答
16

我喜欢这种方法:

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");  
});
于 2012-11-08T22:42:50.087 回答
9

作为@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.
    ),
  ),
);
于 2020-02-18T19:51:10.753 回答
6

throwsA使用with检查异常TypeMatcher

注意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>()));
}); 
于 2019-02-15T10:39:31.457 回答
3

虽然其他答案绝对有效,TypeMatcher<Type>()但现在不推荐使用类似的 API,您必须使用isA<TypeOfException>().

比如之前的,

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

现在将

expect(() => range(5, 2), throwsA(isA<IndexError>()));
于 2020-12-09T05:51:18.267 回答
2

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

Expect.throws(
  // test condition
  (){ 
    throw new Exception('code I expect to throw');
  },
  // exception object inspection
  (err) => err is Exception
);
于 2012-11-09T16:20:34.823 回答
1

我使用了以下方法:

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

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

其次,您需要throwsA结合使用isInstanceOf.

throwsA确保抛出异常,并且isInstanceOf您可以检查是否抛出了正确的异常。

我的单元测试示例:

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

希望这可以帮助。

于 2020-04-28T12:55:17.087 回答