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