2016-04-27 114 views
1

我正在測試使用Mockito模擬對象的方法。當我運行測試時,Mockito告訴我傳入參數的參數與預期不同。如果我在我正在測試的方法中設置斷點,那麼它所調用的參數實際上就是我所期望的。該方法只被調用一次。爲什麼Mockito會報告與我在調試器中看到的內容不同的內容,以及如何解決此問題?Mockito失敗,「參數不同」但調試器顯示不同

下面是測試:

@Test 
public void addExclusivePermutationsTest() { 
    Permutation p1 = mock(Permutation.class); 

    PermutationBuilder pb = new PermutationBuilder(); 

    when(p1.applyPermutations(anySetOf(String.class))) 
      .thenReturn(Collections.singleton("abc123")); 

    pb.addExclusivePermutations(p1); 
    pb.permute("test"); 

    verify(p1).applyPermutations(new HashSet<>(
      Collections.singletonList("test"))); 
} 

測試是非常簡單的。 Permutation是包含方法定義Set<String> applyPermutations(Set<String>)的接口。當在p1上調用該方法時,我告訴Mockito返回包含[abc123]的集合。

addExclusivePermutations(p1)呼叫只是增加了p1到包含Permutation對象的列表的ExclusivePermutation對象。 ExclusivePermutationPermutation實現者所以其applyPermutations方法看起來像這樣:

public Set<String> applyPermutations(final Set<String> stringPermutations) { 
    Set<String> exclusivePermutations = new HashSet<>(); 

    for (Permutation permutation : permutationList) { 
     exclusivePermutations.addAll(permutation.applyPermutations(stringPermutations)); 
    } 

    return exclusivePermutations; 
} 

上述方法被稱爲內部permute("test")。字符串"test"轉換爲Set,並傳入上述方法。上述方法是上的p1。當我用調試器查看這種方法時,stringPermutations僅包含[test],正如我預期的那樣,並且直接傳遞到p1。然後p1返回[abc123],因爲它被嘲笑,並且上述方法與stringPermutations一起返回[test, abc123]。因此,出於某種原因,Mockito說調試器顯示stringPermutations不是[test],而是該方法返回的結果。

最後,這裏是錯誤:

Argument(s) are different! Wanted: 
permutation.applyPermutations(
    [test] 
); 
-> at PermutationBuilderTest$AddExclusivePermutationTests.addExclusivePermutationsTest(PermutationBuilderTest.java:87) 
Actual invocation has different arguments: 
permutation.applyPermutations(
    [abc123, test] 
); 

最後一個音符(對於那些你誰是還在讀書)。如果我通過複製ExclusivePermutation.applyPermutation()而忽略ExclusivePermuation並將其直接放入PermutationBuilder,測試通過。這是一個謎......

編輯:

所以我已經將範圍縮小一點。在PermutationBuilder我有這樣的方法:

public Set<String> permute(String s) { 
    for (Modifier modifier : modifierList) { 
     s = modifier.applyModification(s); 
    } 

    Set<String> stringPermutations = new HashSet<>(Collections.singletonList(s)); 

    for (Permutation permutation : permutationList) { 
     Set<String> result = permutation.applyPermutations(stringPermutations); 
     stringPermutations.addAll(result); 
    } 

    return stringPermutations; 
} 

後,我分配結果,說的Mockito,該方法被調用[test]。但是,當我走到下一行將其添加到stringPermutations時,它將更改爲[abc123, test]。您可以在下面(看底部在arguments陣列)的兩張截圖看到這一點:

After getting result

enter image description here

+0

您是否試過'驗證(p1).applyPermutations(Mockito.eq(new HashSet <>( Collections.singletonList(「test」))));'? –

+0

@RahulSharma我已經試過了,但正如我預料的那樣沒有幫助。問題不在於集合包含相同的元素,而是沒有被評估爲相等。問題是Mockito說這些集合包含不同的元素,但調試器另有說明,我需要弄清楚爲什麼會發生這種情況。 –

回答

1

的問題是,您要修改,您使用的集爭論。

也就是說,在代碼

Set<String> stringPermutations = new HashSet<>(Collections.singletonList(s)); 

for (Permutation permutation : permutationList) { 
    Set<String> result = permutation.applyPermutations(stringPermutations); 
    stringPermutations.addAll(result); 
} 

您創建stringPermutations對象,並添加test它。你現在有一個元素的集合。

然後您撥打permutation.applyPermutations,並將結果添加到stringPermutations

stringPermutations現在包含testabc123

什麼是幾乎肯定會在這裏要說的是是的Mockito不克隆的參數(這將是...棘手的右邊),它只是保留了傳入的對象(S)的參考。

既然你變異stringPermutations調用該方法,認爲的Mockito你叫含testabc123收集的方法,因爲這就是我們的集合中,當它試圖驗證該聲明。解決這個問題的最簡單方法是,在將它傳遞給方法後不要修改集合。

一個解決辦法是:

Set<String> stringPermutations = new HashSet<>(); 

for (Permutation permutation : permutationList) { 
    Set<String> result = permutation.applyPermutations(Collections.singletonList(s)); 
    stringPermutations.addAll(result); 
} 

stringPermutations.addAll(Collections.singletonList(s)); 

如果你真的需要stringPermutations同時包含元素。

+0

你是在現場!很棒,我完全被困住了。謝謝! –