Eqb*_*bal 67 java junit mockito junit-rule
我正在测试一个带有预期异常的方法.我还需要验证在抛出异常之后调用了一些清理代码(在模拟对象上),但看起来忽略了验证.这是代码.我正在使用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(...));
}
Run Code Online (Sandbox Code Playgroud)
似乎verify完全被忽视了.无论我放入什么方法verify,我的测试都是通过,这不是我想要的.
知道为什么会这样吗?
Jef*_*ica 74
ExpectedException通过作品包裹整个测试方法,通过在try-catch块的JUnit @rule.当你的代码抛出异常时,它会将堆栈上升到最近的try/catch,这恰好在ExpectedException实例中(它检查它是你期望的异常).
在Java中,如果方法中发生未捕获的异常,则控件将永远不会返回到该方法中的语句.这里适用相同的规则:在异常之后,Control永远不会返回测试中的语句.
从技术上讲,你可以将验证放在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(...));
}
Run Code Online (Sandbox Code Playgroud)
更新:使用Java 8的lambda表达式,您可以简洁地在try块中包装一个函数接口调用,以使其有用.我想这种语法的支持将进入许多标准测试库.
assertThrows(MyException.class,
() -> systemUnderTest.throwingMethod());
Run Code Online (Sandbox Code Playgroud)
一旦在 UT 中抛出 Exception,下面的所有代码都将被忽略。
@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(...));
}
Run Code Online (Sandbox Code Playgroud)
为了解决这个问题并验证所有调用,我们可以使用try和finally。
@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(...));
}
}
Run Code Online (Sandbox Code Playgroud)
更优雅的解决方案,捕获异常
@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(...));
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
50695 次 |
| 最近记录: |