I have a callback interface that has a method which takes a List
object. I want to use InOrder
to verify that the callback method is called the appropriate number of times, in the correct order, with the correct parameters.
The problem is that Mockito seems to be getting confused because I am passing the same List
object into the method and modifying it between invocations. When I call InOrder.verify()
, I want to verify the value of the List
object at the time in which that method invocation was executed.
Code:
public class Test {
@Test
public void test() {
Callback callback = Mockito.mock(Callback.class);
InOrder inOrder = Mockito.inOrder(callback);
{
List<String> list = new ArrayList<String>(); //note: this List object is inaccessible from the unit test in my real use-case
callback.foo("name1", list);
list.add("value");
callback.foo("name2", list);
}
inOrder.verify(callback).foo("name1", Arrays.<String> asList()); //fails here
inOrder.verify(callback).foo("name2", Arrays.asList("value"));
}
interface Callback {
void foo(String name, List<String> list);
}
}
Error message:
Argument(s) are different! Wanted:
callback.onFoo([]);
Actual invocation has different arguments:
callback.onFoo([value]);
Passing a copy of the List
object into each callback method invocation makes the test pass. But I don't want to create a new List
every time the method is called.
I looked at the MockSettings
object you can pass into Mockito.mock()
, but didn't see anything that might help.
This question is similar to mine. But the solution does not verify the content of the collection that was passed into each method call--it only verifies the fact that some collection was passed into it (anyCollectionOf()
). It verifies the end result, but not the individual invocations.
This answer seemed to provide a potential solution. It uses ArgumentCaptor
to capture the object that is passed into the method. But when I use it to verify the first method call, it returns the List
object after all the modifications were made to it, thus failing the test. I need it to return a List
object whose state matches the List
object's state at that precise invocation.
ArgumentCaptor<List> argument = ArgumentCaptor.forClass(List.class);
inOrder.verify(callback).foo(Mockito.eq("name1"), argument.capture());
assertEquals(Arrays.asList(), argument.getValue()); //fails: "expected: <[]> but was: <[value]>
inOrder.verify(callback).foo(Mockito.eq("name2"), argument.capture());
assertEquals(Arrays.asList("value"), argument.getValue());
How can I get this test to pass without sacrificing any granularity?