Using Mockito I'm trying to verify that certain objects are added and removed from another object. But the function that does this work stores a instance of a collection, updates the contents of this collection, and passes it to my object.
When I then try to verify that addAll and removeAll has been called with the correct objects, it seems Mockito is actually holding onto a reference to the collection, therefore has no idea what the collection contained when the methods were called. A simplified example :
class MySUT
{
private final Collection<Object> objects = new ArrayList<>();
public MySUT(Object firstObject)
{
objects.add(firstObject);
}
public void addNewObject(Collection<Object> other, Object newObject)
{
other.removeAll(objects);
objects.clear();
objects.add(newObject);
other.addAll(objects);
}
}
@Test
public void test()
{
Object firstObject = mock(Object.class);
Object newObject = mock(Object.class);
Collection<Object> myObject = mock(Collection.class);
MySUT sut = new MySUT(firstObject);
sut.addNewObject(myObject, newObject);
verify(myObject).removeAll(eq(Collections.singletonList(firstObject)));
verify(myObject).addAll(eq(Collections.singletonList(newObject)));
}
This test fails claiming that the removeAll
method was called with a list containing newObject
which clearly it wasn't.
I can't use ArgumentCaptor
either as it works the same way - so how can I verify the correct things have been passed to myObject
(obviously in the real code myObject is not a simple collection)?
--
You received this message because you are subscribed to the Google Groups "mockito" group.
To unsubscribe from this group and stop receiving emails from it, send an email to mockito+u...@googlegroups.com.
To post to this group, send email to moc...@googlegroups.com.
Visit this group at http://groups.google.com/group/mockito.
For more options, visit https://groups.google.com/d/optout.
That’s one of the sacrifices Mockito has to make in order to have this API (stub first, act, then verify). It has the benefit to favor immutable design. However when the code has mutable object graph then indeed an custom answer to verify at interaction times. However this kind of coding is not elegant flow wise, I would strongly advise to refactor the code.
Also note that having a anonymous class in the test is not really readable and may confuse on the intent of this answer. I suggest to have a method that return an instance of this answer (you can also use the then
alias of thenAnswer
):
@Test public void test() {
// ...
when(myObject.removeAll(anyCollectionOf(Object.class))).then(recordFirstArgIn(removeAllResult));
sut.addNewObject(myObject, newObject);
// ...
}
// ...
Answer<Object> recordFirstArgIn(Collection<Object>) {
return new Answer<Object>() {
@Override public Object answer(InvocationOnMock invocation) throws Throwable { ... }
}
Cheers,
Brice
--