Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
306 views
in Technique[技术] by (71.8m points)

java - How to verify invocations of the same mock method with the same argument that changes state between invocations in mockito?

I have the following code to be unit tested:

public void foo() {
    Entity entity = //...
    persistence.save(entity);
    entity.setDate(new Date());
    persistence.save(entity);
}

I would like to verify that on the first invocation of persistence.save entity.getDate() returns null.

Therefore I'm unable to use Mockito.verify(/*...*/) because at that time the method foo already completed and entity.setDate(Date) was called.

So I think I need to do verifications of invocations already at the time the invocations happen. How do I do this using Mockito?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

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 properties of the invocations being made. The capturedValues can then be used for simple assertions. The implementation uses Java 8 API. If that is not available one would need to use an interface that is able to convert the InvocationOnMock to the captured value. The usage in the testcase is like this:

@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 capturing that is done by the presented Answer implementation can't be achieved with Mockitos ArgumentCaptor because this is only used after the invocation of the method under test.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...