問題描述
我正在測試一個帶有預期異常的方法.我還需要驗證在拋出異常后(在模擬對象上)調用了一些清理代碼,但看起來驗證被忽略了.這是代碼.我正在使用 Junit ExpectedException
Rule
來驗證預期的異常.
I am testing a method with an expected exception. I also need to verify that some cleanup code was called (on a mocked object) after the exception is thrown, but it looks like that verification is being ignored. Here is the code. I am using the Junit ExpectedException
Rule
to verify the expected 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
完全被忽略了.無論我在 verify
中輸入什么方法,我的測試都通過了,這不是我想要的.
It seems like the verify
is totally being ignored. No matter what method I put in the verify
, my test is passing, which is not what I want.
知道為什么會這樣嗎?
推薦答案
ExpectedException
由 通過 github.com/junit-team/junit/blob/master/src/main/java/org/junit/rules/TestRule.java" rel="noreferrer">JUnit @Rule.當您的代碼拋出異常時,它會向上堆棧到最近的 try/catch,這恰好位于 ExpectedException 實例中(它會檢查它是否是您期望的異常).
ExpectedException
works by wrapping your entire test method in a try-catch block via a JUnit @Rule. When your code throws an exception, it goes up the stack to the nearest try/catch, which happens to be in the ExpectedException instance (which checks that it is the exception you're expecting).
在 Java 中,如果方法中發生未捕獲的異常,則控制權將永遠不會返回到該方法中稍后的語句.此處適用相同的規則:在異常發生后,控制永遠不會返回到測試中的語句.
In Java, if an uncaught exception occurs in a method, control will never return to statements later in that method. The same rules apply here: Control never returns to the statements in your test after the exception.
從技術上講,您可以將驗證放在 finally 塊中,但這往往是 一個壞習慣.您的被測系統可能會拋出意外異常,或者根本沒有異常,這將為您提供有用的失敗消息和跟蹤;但是,如果該失敗導致您的驗證或斷言在 finally
塊中失敗,那么 Java 將顯示這一點,而不是有關意外異常或意外成功的消息.這會使調試變得困難,尤其是因為您的錯誤將來自錯誤根本原因之后的代碼行,錯誤地暗示上面的代碼已成功.
Technically, you could put the verifications in a finally block, but that tends to be a bad habit. Your system-under-test might throw an unexpected exception, or no exception at all, which would give you a helpful failure message and trace; however, if that failure then causes your verifications or assertions to fail in the finally
block, then Java will show that rather than a message about the unexpected exception or unexpected success. This can make debugging difficult, especially because your error will come from lines of code following the root cause of the error, incorrectly implying that the code above it succeeded.
如果您確實需要在異常發生后驗證狀態,則可以基于每個方法,隨時恢復到這個習慣用法:
If you really need to verify state after the exception, on a per-method basis, you can always revert back to this idiom:
@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 塊中 簡潔到有用.我想對這種語法的支持會在許多標準測試庫中找到.
Update: With Java 8's lambda expressions, you can wrap a functional interface call in a try block concisely enough to be useful. I imagine support for this syntax will find its way into many standard testing libraries.
assertThrows(MyException.class,
() -> systemUnderTest.throwingMethod());
這篇關于異常Junit 4.10后的Mockito驗證的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!