How do you validate the call of the same simulation method using the same parameters that change the state between calls in mockito?
I have the following code for unit testing:
public void foo() {
Entity entity = //...
persistence.save(entity);
entity.setDate(new Date());
persistence.save(entity);
}
I want to verify the first call to persistence When saving, entity Getdate() returns null
Therefore, I can't use mockito Verify (/ *... * /), because the method foo has completed and entity is called setDate(Date).
So I think I need to validate the call when it occurs How do I do this with mockito?
Solution
I created the following answer implementation:
public class CapturingAnswer<T,R> implements Answer<T> {
private final Function<InvocationOnMock,R> capturingFunction;
private final List<R> capturedValues = new ArrayList<R>();
public CapturingAnswer(final Function<InvocationOnMock,R> capturingFunction) {
super();
this.capturingFunction = capturingFunction;
}
@Override
public T answer(final InvocationOnMock invocation) throws Throwable {
capturedValues.add(capturingFunction.apply(invocation));
return null;
}
public List<R> getCapturedValues() {
return Collections.unmodifiableList(capturedValues);
}
}
This answer captures the properties of the call in progress The captured values can be used for simple assertions This implementation uses the Java 8 API If this is not available, you need to use an interface that can convert invocationonmock to a captured value The usage in the test case is as follows:
@Test
public void testSomething() {
CapturingAnswer<Void,Date> captureDates = new CapturingAnswer<>(this::getEntityDate)
Mockito.doAnswer(captureDates).when(persistence).save(Mockito.any(Entity.class));
service.foo();
Assert.assertNull(captureDates.getCapturedValues().get(0));
}
private Date getEntityDate(InvocationOnMock invocation) {
Entity entity = (Entity)invocation.getArguments()[0];
return entity.getDate();
}
The capture completed by the rendered answer implementation cannot be implemented using mockitos argumentcaptor because it is only used after the method under test is called
