2012-10-21 27 views
4

我想檢查一個方法未運行,並嘗試使用期望設置times = 0;執行此操作,但是我沒有得到預期的行爲。檢查是否未調用某個方法

例如,下面的測試通過,雖然Session#stop方法被調用,並期望具有times = 0;條件:

public static class Session { 
    public void stop() {} 
} 

public static class Whatever { 
    Session s = new Session(); 
    public synchronized void method() { 
     s.stop(); 
    } 
} 

@Test 
public void testWhatever() throws Exception { 
    new Expectations(Session.class) { 
     @Mocked Session s; 
     { s.stop(); times = 0; } //Session#stop must not be called 
    }; 
    final Whatever w = new Whatever(); 
    w.method(); // this method calls Session#stop => the test should fail... 
       // ... but it passes 
} 

注意:如果我與{ s.stop(); times = 1; }替換代碼,測試通過太:我必須缺少明顯的東西在這裏...

回答

7

意外的嘲弄行爲的原因是,你無意中使用部分嘲諷上嚴格嘲笑類型。在這種情況下,使用times = <n>記錄期望值意味着第一個匹配的調用將被模擬,之後,任何其他調用將執行原始的「unmocked」方法。與常規相反,你會得到預期的行爲(即在調用n後拋出UnexpectedInvocation)。

編寫測試正確的方法是:

public static class Session { public void stop() {} } 
public static class Whatever { 
    Session s = new Session(); 
    public synchronized void method() { s.stop(); } 
} 

@Test 
public void testWhatever() 
{ 
    new Expectations() { 
     @Mocked Session s; 
     { s.stop(); times = 0; } 
    }; 

    final Whatever w = new Whatever(); 
    w.method(); 
} 

可替換地,它也可以用一個驗證塊代替,這對於情況喜歡這些通常是更好的書面:

@Test 
public void testWhatever (@Mocked final Session s) 
{ 
    final Whatever w = new Whatever(); 
    w.method(); 

    new Verifications() {{ s.stop(); times = 0; }}; 
} 
+0

非常感謝 - 這很有道理。 – assylias

+0

答案中的第一個代碼塊仍然不起作用。期望的時間= 0或1都通過!!使用'StrictExpectations'似乎正確地解決了這個問題。 –

0

從內存中,像

verify(s , times(0)).stop(); 

將起作用。麻煩的是,在WhateverSession是不是你@Mock「主編之一,但另一個對象,所以才w.method()前插入

w.s = s; 

乾杯,

+0

我不是非常熟悉jmockit,但我沒有看到任何'verify'方法,我相信嘲笑僅基於類型,所以'ws = s'不是必需的。 – assylias

+2

對不起,這是一個Mockito功能,我錯過了jmockit標籤 - 我的不好。儘管如此,我認爲我的觀點是正確的,那麼模擬的'Session'對象應該如何與'Whatever'會話對象有什麼關係(至少它是如何與Mockito一起工作的)? –

+0

在jmockit中,你模擬一個類型,而不是一個實例。所以在我的例子中,所有的Session實例都應該被模擬。除非我誤解了一些當然;-)無論如何,謝謝。 – assylias

0

我找到了一個解決方法與MockUp類 - 如預期下測試失敗 - 我還是想明白,爲什麼原來的做法是行不通的

@Test 
public void testWhatever() throws Exception { 
    new MockUp<Session>() { 
     @Mock 
     public void stop() { 
      fail("stop should not have been called"); 
     } 
    }; 
    final Whatever w = new Whatever(); 
    w.method(); 
} 
1

與此相關我遇到了JMockit,times = 0和@Tested註解的問題。

使用@Tested註解,您仍然有一個'真實'類,所以當在這個真實類上註冊期望或驗證(即使是times = 0)時,JMockit會嘗試執行該方法。解決方案是將部分地在嘲笑的期望類:

@Tested 
Session s; 

new Expectations(Session.class) {{ 
    s.stop(); times = 0; } //Session#stop must not be called 
}; 

這是我發現使用次數= 0上從@Tested類的方法的唯一途徑。

0

嘗試maxTimes相反,你還可以在一個靜態的方式引用的stop():

@Test 
public void test(@Mocked Session mockSession){ 

    final Whatever w = new Whatever(); 
    w.method(); 

    new Verifications(){ 
    { 
     Session.stop(); 
     maxTimes = 0; 
    } 
    }; 
} 
相關問題