We came across really nasty problem with Mockito.
Code:
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));
}
}
This causes error message like:
Arguments are different! Wanted:
foo.bar([1,2,3]);
Actual invocation has different arguments:
foo.bar([]);
What just happened:
Mockito records reference to list
rather than copy of list
, so in the code above Mockito verifies against modified version (empty list, []
) instead to the one actually passed during invocation ([1,2,3]
)!
Question:
Is there any elegant and clean solution to this problem other than doing a defensive copy like below (which actually helps but we don't like this solution)?
public void fun(){
list = Arrays.asList(1,2,3);
foo.bar(new ArrayList(list));
list.clear();
}
We don't want to modify correct production code and reduce its performance only to fix technical problem with test.
I'm asking this question here because it seems to be possibly common problem with Mockito. Or we just do something wrong?
PS. This is not a real code so please don't ask why we create a list and then clear it etc. In real code we have a real need to do something similar :-).