Mockito在例外Junit 4.10之后进行validation

我正在testing一个预期的例外的方法。 我还需要validation在引发exception之后调用了一些清理代码(在模拟对象上),但看起来validation被忽略。 这是代码。 我正在使用Junit ExpectedException Rule来validation预期的exception。

 @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完全被忽略。 不pipe我用什么方法进行verify ,我的testing都通过了,这不是我想要的。

任何想法,为什么这种事情发生?

ExpectedException通过将整个testing方法通过JUnit @Rule 包装在try-catch块中。 当你的代码抛出一个exception时,它会把堆栈上传到最近的try / catch,恰好在ExpectedException实例中(它检查它是你期望的exception)。

在Java中,如果方法中发生未捕获的exception,则控制将永远不会返回到该方法中的语句。 这里适用相同的规则: 在exception之后,控制从不返回到testing中的语句。

从技术上讲,你可以把validation放在一个最后的块里,但这往往是一个坏习惯 。 在任何情况下,它都可能吞下有用的ExpectedException消息,因为它会在ExpectedException规则可以拦截之前运行。

如果您确实需要在exception之后validation状态,则可以在每个方法的基础上始终回到这个方式:

 @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的lambdaexpression式,可以简洁地将一个函数接口调用包装在一个try块中,以便有用 。 我想这个语法的支持将会进入许多标准的testing库。

 assertThrows(MyException.class, () -> systemUnderTest.throwingMethod()); 

捕捉exception更优雅的解决scheme

 @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(...)); } 

我还没有尝试过,但除了杰夫鲍曼的杰出的答案,你可能有select使用ExpectedException规则与try … finally构造,将您的validation语句在finally块。