我测试与预期异常的方法。 我还需要核实一些清理代码被称为(一个嘲笑对象)的异常被抛出之后,但它看起来像核查被忽略。 下面是代码。 我使用JUnit ExpectedException
Rule
来验证预期的异常。
@Rule
public ExpectedException expectedEx = ExpectedException.none();
@Test
public void testExpectedException()
{
MockedObject mockObj = mock(MockedObj.class);
MySubject subject = new MySubject(mockedObj);
expectedEx.expect(MyException.class);
expectedEx.expectMessage("My exception message.");
subject.someMethodThrowingException();
verify(mockObj).
someCleanup(eq(...));
}
这似乎是verify
是完全被忽略。 无论我提出什么方法的verify
,我测试合格,这不是我想要的。
任何想法,为什么多数民众赞成happenning?
ExpectedException
工作原理是包裹整个测试方法,通过在try-catch块的JUnit @rule 。 当你的代码抛出一个异常,这是不言而喻的堆栈到最近的try / catch,这恰好是在的ExpectedException实例(检查它是你期待的除外)。
在Java中,如果一个方法发生了未捕获的异常,控制永远不会返回到报表中该方法后。 适用同样的规则在这里: 控制永远不会返回到异常后,测试的语句。
从技术上讲,你可以把验证在finally块,但往往是一个坏习惯 。 编辑:您的系统下测试可能会引发意外的异常,或也不例外可言,它会给你一个有用的失败消息和跟踪; 但是,如果失败则使您的验证和断言在失败finally
块,那么Java将显示,而不是一个关于意外的异常或意外成功的消息。 这可以使调试困难,特别是因为你的错误将来自以下错误的根本原因的代码行,错误地暗示其上面的代码成功。
如果你真的需要异常后,验证状态,在每一方法的基础,你可以随时恢复到这个成语:
@Test
public void testExpectedException()
{
MockedObject mockObj = mock(MockedObj.class);
MySubject subject = new MySubject(mockedObj);
try {
subject.someMethodThrowingException();
fail("Expected MyException.");
} catch (MyException expected) {
assertEquals("My exception message.", expected.getMessage());
}
verify(mockObj).someCleanup(eq(...));
}
更新:使用Java 8的Lambda表达式,你可以用在try块的功能接口调用简洁足够有用 。 我想支持这个语法会找到自己的方式为许多标准的测试库。
assertThrows(MyException.class,
() -> systemUnderTest.throwingMethod());
用更优雅的解决方案捕获的异常
@Test
public void testExpectedException()
{
MockedObject mockObj = mock(MockedObject.class);
MySubject subject = new MySubject(mockObj);
when(subject).someMethodThrowingException();
then(caughtException())
.isInstanceOf(MyException.class)
.hasMessage("My exception message.");
verify(mockObj).someCleanup(eq(...));
}
我没有试过呢,但除了杰夫·鲍曼的出色答卷,您可能需要使用的ExpectedException规则与一个try ... finally结构的选择,把你的验证声明finally块。
一旦异常被抛出UT,下面所有的代码都将被忽略。
@Test(expected = Exception.class)
public void testExpectedException() {
MockedObject mockObj = mock(MockedObj.class);
MySubject subject = new MySubject(mockedObj);
subject.doSomething(); // If this line results in an exception then all the code below this will be ignored.
subject.someMethodThrowingException();
verify(mockObj).
someCleanup(eq(...));
}
为了解决这个问题,并确认所做的所有来电,我们可以用试图用最后 。
@Test(expected = Exception.class)
public void testExpectedException() {
MockedObject mockObj = mock(MockedObj.class);
MySubject subject = new MySubject(mockedObj);
try {
subject.someMethodThrowingException();
} finally {
verify(mockObj).
someCleanup(eq(...));
}
}