在测试抛出异常的方法时验证行为
Verifying behavior when testing a method that throws an exception
最近,在代码审查中,一位同事说"Tests should not have try-catch blocks"。他还向我指出了有关 ExpectedException
的信息,我能够使用它来重写我的一些正在对异常数据执行检查的测试。
但是,我遇到了一种情况,我不确定是否可以消除 try-catch。我正在为将抛出异常 and 的方法编写单元测试,该异常将执行一些我需要使用 JMockit 验证的行为。假设被测代码包含类似
的内容
try {
...code...
} catch (SomeException e) {
statusMessage.send("Failure", <parameters with some data>);
throw e;
}
JUnit 测试目前看起来像
@Test
public void test() {
... set things up ...
try {
callTheMethod();
fail("No exception thrown");
} catch (Exception e) {
assertEquals(SomeException.class, e.getClass());
}
new Verifications() { {
statusMessage.send("Failure", <expected data>);
} }
}
我找不到摆脱 try-catch 的好方法。我个人认为将它放在那里没有问题,但如果我不至少 尝试 摆脱它,我可能会 赶上 我的同事见鬼了 :) :) :)
fail
和 assertEquals
不是必需的。如果有一种简单的方法可以告诉 JUnit/JMockit 忽略来自 callTheMethod()
的任何异常并继续,那很好——我可以创建另一个测试来检查异常。
是否有一些 JUnit 或 JMockit 功能可以让我完成我想做的事情?
[注意:经过编辑以明确我正在测试的行为是对模拟对象的调用,而不是静态方法调用。它确实与问题无关。]
基于 API,我想你可以这样做:
class AjbUnitTest
{
@Rule
public ExpectedException thrown = ExpectedException.none();
@Test
public void test()
{
... set things up ...
thrown.expect(SomeException.class)
callTheMethod(); / Preumably this throws SomeException
...
}
}
对于特定于异常的断言 AssertJ 有一个很好的 API:
@Test
public void testException() {
assertThatThrownBy(() -> { throw new Exception("error!") })
.isInstanceOf(Exception.class)
.hasMessageContaining("error");
}
基本上,您可以 "collect" 异常而不中断测试执行。
您的同事在一般意义上可能是正确的,使用 try-catch
来测试您的异常处理不如使用提供的 ExpectedException
实用程序可取。但是,我认为该规则不适用于您的情况;捕获异常,以便您可以验证其他事情是否完全合理。没有其他方法可以阻止异常传播,AFAIK。
目前,如果您想在抛出断言后验证某些内容,则必须使用普通 JUnit try-catch
。使用 JUnit 4.13(尚未发布)您可以使用
expectThrows(Exception.class, () -> callTheMethod());
new Verifications() { {
statusMessage.send("Failure", <expected data>);
} }
作为替代方法,您可以使用 Fishbowl's ignoreException.
ignoreException(() -> callTheMethod());
new Verifications() { {
statusMessage.send("Failure", <expected data>);
} }
完全披露:我是 Fishbowl 的作者。
最近,在代码审查中,一位同事说"Tests should not have try-catch blocks"。他还向我指出了有关 ExpectedException
的信息,我能够使用它来重写我的一些正在对异常数据执行检查的测试。
但是,我遇到了一种情况,我不确定是否可以消除 try-catch。我正在为将抛出异常 and 的方法编写单元测试,该异常将执行一些我需要使用 JMockit 验证的行为。假设被测代码包含类似
的内容try {
...code...
} catch (SomeException e) {
statusMessage.send("Failure", <parameters with some data>);
throw e;
}
JUnit 测试目前看起来像
@Test
public void test() {
... set things up ...
try {
callTheMethod();
fail("No exception thrown");
} catch (Exception e) {
assertEquals(SomeException.class, e.getClass());
}
new Verifications() { {
statusMessage.send("Failure", <expected data>);
} }
}
我找不到摆脱 try-catch 的好方法。我个人认为将它放在那里没有问题,但如果我不至少 尝试 摆脱它,我可能会 赶上 我的同事见鬼了 :) :) :)
fail
和 assertEquals
不是必需的。如果有一种简单的方法可以告诉 JUnit/JMockit 忽略来自 callTheMethod()
的任何异常并继续,那很好——我可以创建另一个测试来检查异常。
是否有一些 JUnit 或 JMockit 功能可以让我完成我想做的事情?
[注意:经过编辑以明确我正在测试的行为是对模拟对象的调用,而不是静态方法调用。它确实与问题无关。]
基于 API,我想你可以这样做:
class AjbUnitTest
{
@Rule
public ExpectedException thrown = ExpectedException.none();
@Test
public void test()
{
... set things up ...
thrown.expect(SomeException.class)
callTheMethod(); / Preumably this throws SomeException
...
}
}
对于特定于异常的断言 AssertJ 有一个很好的 API:
@Test
public void testException() {
assertThatThrownBy(() -> { throw new Exception("error!") })
.isInstanceOf(Exception.class)
.hasMessageContaining("error");
}
基本上,您可以 "collect" 异常而不中断测试执行。
您的同事在一般意义上可能是正确的,使用 try-catch
来测试您的异常处理不如使用提供的 ExpectedException
实用程序可取。但是,我认为该规则不适用于您的情况;捕获异常,以便您可以验证其他事情是否完全合理。没有其他方法可以阻止异常传播,AFAIK。
目前,如果您想在抛出断言后验证某些内容,则必须使用普通 JUnit try-catch
。使用 JUnit 4.13(尚未发布)您可以使用
expectThrows(Exception.class, () -> callTheMethod());
new Verifications() { {
statusMessage.send("Failure", <expected data>);
} }
作为替代方法,您可以使用 Fishbowl's ignoreException.
ignoreException(() -> callTheMethod());
new Verifications() { {
statusMessage.send("Failure", <expected data>);
} }
完全披露:我是 Fishbowl 的作者。