2016-04-13 40 views
0

我有一個在數百個測試中使用的實用程序方法來模擬來自定製隨機程序的返回值。下面是我的代碼(高度人工化)模式:使用'when'作爲驗證

interface CardRandomiser{ 
    Card getCard(Suit suit); 
} 

void mockCard(Suit suit, Face face) { 
    CardRandomiser rand = mock(CardRandomiser.class); 
    when(rand.getCard(suit)).thenReturn(new Card(suit, face)); 
    Game.setCardRandomiser(rand); 
} 

這可以被用來作爲:

mockCard(Suit.CLUBS, Face.QUEEN); 
Card card = pickACardAnyCard(); 
assertThat(card.getFace(), is(Face.QUEEN)); 

但是這使得一些bug有點難以回暖。如果被測方法錯誤地要求Suit.HEARTS,那麼模擬返回null,並且斷言正確失敗。但是不可能通過錯誤消息告訴傳遞給模擬的東西。

很明顯,我可以用verify來處理這個問題。我可以將模擬從mockCard函數中取出,然後分別驗證是否使用了正確的值。但是這確實會使測試斷言混亂,而這些斷言與測試的內容並不真正相關。鑑於每次調用這個方法,我都會指定一個期望的參數值,我寧願將斷言放在一個地方。請注意,這一切都發生在調用之前的之前。

理想情況下,我想when語句拋出異常,如果它被調用一個意外的值。喜歡的東西:

when(rand.getCard(suit)).thenReturn(new Card(suit, face)); 
when(rand.getCard(intThat(not(is(suit))))).thenThrow(new IllegalArgumentException()); 

這工作和停止時getCard被稱爲這是更好的測試。但它仍然不允許我顯示錯誤的論點。

我也嘗試過使用ArgumentCaptor然後檢查捕獲的值。但很明顯,它們是用於verify陳述而不是when陳述。

有沒有這樣做的標準Mockito方式,還是我需要用verify陳述來混亂我的測試?

回答

2

您可以使用thenAnswer配置mockito答案,例如,

private CardRandomiser mockCard(final Suit suit, final Face face) { 
    CardRandomiser rand = mock(CardRandomiser.class); 

    when(rand.getCard(any(Suit.class))).thenAnswer(new Answer<Card>() { 
     @Override 
     public Card answer(InvocationOnMock invocation) throws Throwable { 
      if(!suit.equals(invocation.getArguments()[0])) { 
       throw new IllegalArgumentException(
         String.format("Value %s passed, but mocked for %s", invocation.getArguments()[0], suit)); 
      } 
      return new Card(suit, face); 
     } 
    }); 

    return rand; 
} 
+0

這很完美。謝謝。 – sprinter