2012-11-05 31 views
49

我正在測試一個預期異常的方法。我還需要驗證在引發異常之後調用了一些清理代碼(在模擬對象上),但看起來似乎忽略了驗證。這是代碼。我正在使用Junit ExpectedExceptionRule來驗證預期的異常。Mockito在異常之後進行驗證Junit 4.10

@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中輸入什麼方法,我的測試都通過了,這不是我想要的。

任何想法爲什麼這種事情發生?

回答

51

ExpectedException作品wrapping your entire test method通過JUnit @Rule在try-catch塊。當你的代碼拋出一個異常時,它將堆棧上傳到最近的try/catch,恰好在ExpectedException實例中(它檢查它是你期望的異常)。在Java中,如果方法中發生未捕獲的異常,則控制將永遠不會返回到該方法中的後面的語句。這裏適用相同的規則:在異常之後,控制從不會返回到您的測試中的語句。

從技術上講,你可以把驗證放在finally塊中,但是這往往是a bad habit。在任何情況下,它都可能吞下有用的ExpectedException消息,因爲它會在ExpectedException規則可以攔截之前運行。

如果你真的需要異常後,驗證狀態,在每一方法的基礎,你可以隨時恢復到這個成語:

@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塊concisely enough to be useful中包裝功能性接口調用。我認爲對這種語法的支持將會進入許多標準測試庫。

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

我沒有試過呢,但除了傑夫·鮑曼的出色答卷,您可能需要使用的ExpectedException規則與選擇一個try ... finally構造,將您的驗證聲明在最後塊。

+0

更優雅的解決方案檢查我的中間段...我認爲這工作,但會吞下的ExpectedException消息。儘管感謝恭維! –

+0

錯過了 - 可能是正確的。 –

+3

終於正常工作 - 執行驗證,仍然檢測到預期的異常,它的消息 –

6

catch-exception

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