我们在 Mockito 上遇到了非常讨厌的问题。
代码:
public class Baz{
private Foo foo;
private List list;
public Baz(Foo foo){
this.foo = foo;
}
public void invokeBar(){
list = Arrays.asList(1,2,3);
foo.bar(list);
list.clear();
}
}
public class BazTest{
@Test
void testBarIsInvoked(){
Foo mockFoo = mock(Foo.class);
Baz baz = new Baz(mockFoo);
baz.invokeBar();
verify(mockFoo).bar(Arrays.asList(1,2,3));
}
}
这会导致错误消息,如:
Arguments are different! Wanted:
foo.bar([1,2,3]);
Actual invocation has different arguments:
foo.bar([]);
刚才发生了什么:
Mockito 记录对 的引用而list
不是副本list
,因此在上面的代码中,Mockito 验证修改后的版本(空列表,[]
),而不是调用期间实际传递的版本([1,2,3]
)!
问题:
除了像下面那样做一个防御性副本(这实际上有帮助,但我们不喜欢这个解决方案)之外,是否有任何优雅而干净的解决方案来解决这个问题?
public void fun(){
list = Arrays.asList(1,2,3);
foo.bar(new ArrayList(list));
list.clear();
}
我们不想修改正确的生产代码并降低其性能,只是为了解决测试的技术问题。
我在这里问这个问题是因为这似乎是 Mockito 的常见问题。或者我们只是做错了什么?
PS。这不是一个真实的代码,所以请不要问我们为什么要创建一个列表然后清除它等等。在真实的代码中,我们确实需要做类似的事情:-)。