We ran into a very 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 an error message like:
Arguments are different! Wanted: foo.bar([1,2,3]); Actual invocation has different arguments: foo.bar([]);
What just happened:
Mockito writes the link to list instead of copying list , so in the code above Mockito checks instead of the modified version (empty list, [] ) instead of the one that was actually passed during invocation ( [1,2,3] )!
Question:
Is there an elegant and clean solution to this problem besides creating a protective copy, as shown below (which actually helps, but we donβt like it)?
public void fun(){ list = Arrays.asList(1,2,3); foo.bar(new ArrayList(list)); list.clear(); }
We do not want to change the production code to the correct one and reduce its performance only to eliminate a technical problem with the test.
I ask this question here because it is possibly a common problem with Mockito. Or are we just doing something wrong?
PS. This is not real code, so please donβt ask why we create a list and then clear it, etc. In real code, we really need to do something like this :-).