2016-04-27 107 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

你是在现场!很棒,我完全被困住了。谢谢! –