的Java 8使这是一个容易得多,并且科特林/斯卡拉更是如此。
我们可以写一个小工具类
class MyAssertions{
public static void assertDoesNotThrow(FailingRunnable action){
try{
action.run()
}
catch(Exception ex){
throw new Error("expected action not to throw, but it did!", ex)
}
}
}
@FunctionalInterface interface FailingRunnable { void run() throws Exception }
,然后你的代码变得简单:
@Test
public void foo(){
MyAssertions.assertDoesNotThrow(() -> {
//execute code that you expect not to throw Exceptions.
}
}
如果你没有访问Java-8,我会用一个痛苦的旧Java设施:任意代码块和简单评论
//setup
Component component = new Component();
//act
configure(component);
//assert
/*assert does not throw*/{
component.doSomething();
}
最后,用kotlin,一种我用过的语言最近爱上了:
fun (() -> Any?).shouldNotThrow()
= try { invoke() } catch (ex : Exception){ throw Error("expected not to throw!", ex) }
@Test fun `when foo happens should not throw`(){
//...
{ /*code that shouldn't throw*/ }.shouldNotThrow()
}
虽然有很多的空间你到底要怎么表达这个摆弄,我一直的fluent assertions风扇。
关于
你接近这个错误的方式。只需测试您的功能:如果抛出异常,测试将自动失败。如果没有发生异常,您的测试将全部变为绿色。
这在原则上是正确的,但在结论上不正确。
Java允许控制流的异常。这通过JRE运行时本身在Double.parseDouble
之类的API中通过NumberFormatException
和Paths.get
经由InvalidPathException
完成。
鉴于你已经编写了一个验证Double.ParseDouble
的数字字符串的组件,也许使用正则表达式,也许是手写的解析器,或者是嵌入了一些其他域规则,这些规则将双精度范围限制到某个特定的值,如何最好地测试这个组件?我认为一个明显的测试是断言,当分析结果字符串时,不会引发异常。我会使用上面的assertDoesNotThrow
或/*comment*/{code}
块来编写该测试。喜欢的东西
@Test public void given_validator_accepts_string_result_should_be_interpretable_by_doubleParseDouble(){
//setup
String input = "12.34E+26" //a string double with domain significance
//act
boolean isValid = component.validate(input)
//assert -- using the library 'assertJ', my personal favourite
assertThat(isValid).describedAs(input + " was considered valid by component").isTrue();
assertDoesNotThrow(() -> Double.parseDouble(input));
}
我也建议你使用Theories
或Parameterized
,让您可以更轻松地重新使用这个测试对于其他输入参数此项测试input
。或者,如果你想去异国情调,你可以去test-generation tool(和this)。 TestNG对参数化测试有更好的支持。
我发现特别令人不快的建议是使用@Test(expectedException=IllegalArgumentException.class)
,这个例外是危险广泛的。如果你的代码发生了变化,使得测试组件的构造函数有if(constructorArgument <= 0) throw IllegalArgumentException()
,并且你的测试为这个参数提供了0,因为它很方便 - 这是很常见的,因为好的生成测试数据是一个令人惊讶的难题 - 那么你的尽管它没有测试任何东西,但测试将是绿色条。这样的测试比无用的更糟糕。
JUnit测试判断,如果它抛出一个比预期的异常之外的任何异常都失败了。通常不会有例外。 – Raedwald
JUnit中的失败和错误没有区别吗?第一种意思是测试失败,第二种意思是意外事件发生。 – Vituel
可能的重复[如何测试如果不引发特定的异常?](http://stackoverflow.com/questions/8575653/how-can-i-test-if-a-particular-exception-is-not -thrown) –