2016-08-05 54 views
1

我有一個回調接口,其方法需要List對象。我希望使用InOrder來驗證回調方法是否按照正確的順序被正確的參數調用了適當的次數。使用InOrder驗證更改List對象的方法調用

問題是,Mockito似乎越來越困惑,因爲我將相同的List對象傳入方法並在調用之間對其進行修改。當我打電話給InOrder.verify()時,我想驗證List對象在執行該方法調用時的值

代碼:

public class Test { 
    @Test 
    public void test() { 
     Callback callback = Mockito.mock(Callback.class); 
     InOrder inOrder = Mockito.inOrder(callback); 

     { 
      List<String> list = new ArrayList<String>(); //note: this List object is inaccessible from the unit test in my real use-case 
      callback.foo("name1", list); 
      list.add("value"); 
      callback.foo("name2", list); 
     } 

     inOrder.verify(callback).foo("name1", Arrays.<String> asList()); //fails here 
     inOrder.verify(callback).foo("name2", Arrays.asList("value")); 
    } 

    interface Callback { 
     void foo(String name, List<String> list); 
    } 
} 

錯誤消息:

Argument(s) are different! Wanted: 
callback.onFoo([]); 
Actual invocation has different arguments: 
callback.onFoo([value]); 

跑過List對象的副本每個回調方法調用,使試驗合格。但每次調用方法時,我都不想創建新的List

我看着MockSettings對象,你可以通過Mockito.mock(),但沒有看到任何可能的幫助。

This question與我的相似。但該解決方案不驗證已傳遞到每個方法調用的集合的內容 - 它僅驗證某些集合已傳入它的事實(anyCollectionOf())。它驗證最終結果,但不是個別調用

This answer似乎提供了一個潛在的解決方案。它使用ArgumentCaptor來捕獲傳入該方法的對象。但是,當我使用它來驗證第一個方法調用時,它在對所做的所有修改都返回List對象,從而使測試失敗。我需要它返回一個List對象,該對象的狀態匹配List對象的狀態,該對象的確切調用爲

ArgumentCaptor<List> argument = ArgumentCaptor.forClass(List.class); 

inOrder.verify(callback).foo(Mockito.eq("name1"), argument.capture()); 
assertEquals(Arrays.asList(), argument.getValue()); //fails: "expected: <[]> but was: <[value]> 

inOrder.verify(callback).foo(Mockito.eq("name2"), argument.capture()); 
assertEquals(Arrays.asList("value"), argument.getValue()); 

如何在不犧牲任何粒度的情況下通過此測試?

+0

如果您打算在我所建議的副本中使用我的anser,您可以在捕獲功能中創建列表副本。之後在驗證階段,您可以檢查這些副本是否正確。 – SpaceTrucker

+0

謝謝@SpaceTrucker。不理想,但它的工作原理。 – Michael

回答

0

question that @SpaceTrucker linked to提供了一個解決方案。

基本上,爲該方法創建一個自定義Answer,並在每次調用該方法時存儲參數List的副本。然後,確認所有的副本都是你期望的副本。這不是理想的,但它的工作原理。

@Test 
public void test() { 
    Callback callback = Mockito.mock(Callback.class); 

    final List<List<String>> listParameters = new ArrayList<List<String>>(); 
    Mockito.doAnswer(new Answer<Void>() { 
     public Void answer(InvocationOnMock invocation) throws Throwable { 
      List<String> list = (List<String>) invocation.getArguments()[1]; 
      listParameters.add(new ArrayList<String>(list)); 
      return null; 
     } 
    }).when(callback).foo(Mockito.anyString(), Mockito.anyList()); 

    { 
     List<String> list = new ArrayList<String>(); //note: this List object is inaccessible from the unit test in my real use-case 
     callback.foo("name1", list); 
     list.add("value"); 
     callback.foo("name2", list); 
    } 

    InOrder inOrder = Mockito.inOrder(callback); 
    inOrder.verify(callback).foo(Mockito.eq("name1"), Mockito.anyList()); 
    inOrder.verify(callback).foo(Mockito.eq("name2"), Mockito.anyList()); 

    Assert.assertEquals(Arrays.asList(
     Arrays.asList(), 
     Arrays.asList("value") 
    ), listParameters); 
} 
+0

如果你說「這不理想」,你認爲可能會更好嗎? – SpaceTrucker

+0

@SpaceTrucker如果我的原始代碼工作會更好。解決方案冗長,閱讀不好。 – Michael

相關問題