2012-09-16 70 views
0

我有一個非常簡單的方法,我試圖單元測試:的JUnit /的Mockito試驗失敗的離奇原因

public class MyAntTask extends org.apache.tools.ant.Task { 
    public void execute() { 
     fire(); 
    } 

    public void fire() { 
     // Do stuff 
    } 
} 

我只想寫一個單元測試,確認調用​​總是調用fire(),所以我寫了這個:

@Test 
public void executeCallsFire() { 
    //GIVEN 
    MyAntTask myTask = Mockito.mock(MyAntTask.class); 

    // Configure the mock to throw an exception if the fire() method 
    // is called. 
    Mockito.doThrow(new RuntimeException("fired")).when(myTask).fire(); 

    // WHEN 
    try { 
     // Execute the execute() method. 
     myTask.execute(); 

     // We should never get here; HOWEVER this is the fail() that's 
     // being executed by JUnit and causing the test to fail. 
     Assert.fail(); 
    } 
    catch(Exception exc) { 
     // THEN 
     // The fire() method should have been called. 
     if(!exc.getMessage().equals("fired")) 
      Assert.fail(); 
    } 
} 

我想(我決不是一個專家)通常的Mockito不能返回void,但是這是一個解決辦法模擬的方法。你基本上說「用一個Mock包裝我的對象,每當一個特定的方法即將被執行時,它總會返回一個特定的RuntimeException」。因此,Mockito不是實際執行fire(),而是看到它即將執行並引發異常。執行已驗證?檢查。

而不是通過,它在第一個Assert.fail()失敗,正好在myTask.execute()的呼叫之下。

對於我的生活,我無法弄清楚爲什麼。下面是巨大的堆棧跟蹤的JUnit的第一個10或-所以線是給我的失敗:

java.lang.AssertionError 
    at org.junit.Assert.fail(Assert.java:92) 
    at org.junit.Assert.fail(Assert.java:100) 
    at net.myproj.ant.tasks.MyAntTaskUnitTest.executeCallsFire(MyAntTaskUnitTest.java:32) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
    at java.lang.reflect.Method.invoke(Method.java:616) 

任何這裏的想法,你們StackOverflow的的大師的Mockito?提前致謝!

+0

雖然fgb的答案是完全正確的,但我想知道你爲什麼要單元測試一行長,沒有邏輯的方法。有一點,單元測試不再是你的時間經濟用途。我從來沒有找到一個很好的理由來編寫一個像這個一樣簡單的方法的單元測試。 –

回答

6

由於myTask是一個模擬,真正的對象根本不會被調用。要調用一個真實的物體,請使用間諜。

您可以測試使用驗證調用方法,因此不需要例外。

public void executeCallsFire() { 
    MyAntTask myTask = Mockito.spy(new MyAntTask()); 

    myTask.execute(); 

    Mockito.verify(myTask).fire(); 
} 

想嘲笑你正在測試的對象似乎不正確。設計測試通常會更好,以便驗證對單獨對象的調用。

+0

Mockito團隊不贊同加上間諜作爲部分嘲諷。 – Brice

0

我在這裏看到更多的設計問題:

  1. 爲什麼你需要一個線方法和他們兩個都公開?
  2. 這些模擬是用來模擬依賴關係,而不是用於測試的類
  3. 如果你會使私人火災(名字不太清楚)。你不應該測試你的類的私人行爲