你如何在 Dart 中对异常进行单元测试?
Posted
技术标签:
【中文标题】你如何在 Dart 中对异常进行单元测试?【英文标题】:How do you unittest exceptions in Dart? 【发布时间】:2012-10-29 05:39:10 【问题描述】:考虑一个根据传递的参数进行一些异常处理的函数:
List range(start, stop)
if (start >= stop)
throw new ArgumentError("start must be less than stop");
// remainder of function
如何测试是否引发了正确类型的异常?
【问题讨论】:
【参考方案1】:在这种情况下,有多种方法可以测试异常。简单地测试是否引发了非特定异常:
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 提供最后 2 个解决方案)。
【讨论】:
我在做expect(range(5, 3), throwsArgumentError)
,但在期望中没有捕获到异常。期望的第一个参数必须是一个匿名函数,在调用时最终会抛出。您的回答帮助我找到了那个愚蠢的错误,谢谢!
同时 new isInstanceOf<ArgumentError>()
已被弃用。应该使用 TypeMatcher:例如throwsA(TypeMatcher<Exception>())
使用 TypeMatcher 似乎不再有效。有效的是throwsA(isA<Exception>())
这绝对是最好的答案,但我想知道为什么对于如此简单的任务语法必须如此冗长..
你不能没有闭包来进行测试,但是如果你需要这么多时间,可以考虑为更简洁的代码创建一个自定义匹配器。【参考方案2】:
我喜欢这种方法:
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");
);
【讨论】:
它比其他选项更冗长,但它的可读性很强,而且它并不假设你已经记住了整个 unittest 库;)【参考方案3】:作为@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.
),
),
);
【讨论】:
【参考方案4】:使用throwsA
和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>()));
);
【讨论】:
我错过了 expect() 方法的 () => sintaxe。谢谢。【参考方案5】:虽然其他答案肯定是有效的,但像 TypeMatcher<Type>()
这样的 API 现在已弃用,您必须使用 isA<TypeOfException>()
。
例如,以前是什么,
expect(() => range(5, 2), throwsA(TypeMatcher<IndexError>()));
现在是
expect(() => range(5, 2), throwsA(isA<IndexError>()));
【讨论】:
【参考方案6】:对于简单的异常测试,我更喜欢使用静态方法API:
Expect.throws(
// test condition
()
throw new Exception('code I expect to throw');
,
// exception object inspection
(err) => err is Exception
);
【讨论】:
它对我不起作用。似乎 Expect.throws() 被删除了。【参考方案7】:我使用了以下方法:
首先你需要将你的方法作为一个 lambda 传递给期望函数:
expect(() => method(...), ...)
其次,您需要将throwsA
与isInstanceOf
结合使用。
throwsA
确保抛出异常,使用isInstanceOf
您可以检查是否抛出了正确的异常。
我的单元测试示例:
expect(() => parser.parse(raw), throwsA(isInstanceOf<FailedCRCCheck>()));
希望这会有所帮助。
【讨论】:
以上是关于你如何在 Dart 中对异常进行单元测试?的主要内容,如果未能解决你的问题,请参考以下文章