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
262 views
in Technique[技术] by (71.8m points)

java - Why mockito will trigger the verify twice?

I notice this problem during the following test:

verify(mockedObject).functionCall(argThat(inputStream -> {
    final String content = ... // read the inputStream
    assertEquals(expectedContent, content);
    return true;
}));

It will actually fail although the assertEquals assertion is true. I debug the test, find that the lambda function is reached twice, and at the second time, the cursor of the stream is at the end of the stream. That's why it fails.

So I have to reset the stream first:

verify(mockedObject).functionCall(argThat(inputStream -> {
    inputStream.reset();
    final String content = ... // read the inputStream
    assertEquals(expectedContent, content);
    return true;
}));

The question is, why the lambda is triggered twice? Is this by design? Does it have a document?

Mockito version: 2.22

Junit version: 5.6.0

Java version: 1.8

Update

The method is called exactly once, and the inputs of two lambda calls are exactly the same input. Actually, they are the same object. The only thing I have to do is to reset the stream, as it has been exhausted by the first lambda call.


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

1 Answer

0 votes
by (71.8m points)

I wouldn't say it's "by design", rather that it's what the current implementation does. The Mockito Times class which performs your assertions has the following method (I'm on a pretty recent version so YMMV):

public void verify(VerificationData data) {
    List<Invocation> invocations = data.getAllInvocations();
    MatchableInvocation wanted = data.getTarget();

    if (wantedCount > 0) {
        checkMissingInvocation(data.getAllInvocations(), data.getTarget());
    }
    checkNumberOfInvocations(invocations, wanted, wantedCount);
}

Both checkMissingInvocation and checkNumberOfInvocations perform independent filtering on the list of all invocations to retain the relevant ones, so any matcher you declare ends up being executed twice for each invocation. It's actually exactly the same call:

List<Invocation> actualInvocations = findInvocations(invocations, wanted);

Maybe the filtered list could be cached, but the point is that unless otherwise specified in the documentation, you cannot assume that the function you supply will be executed only once. Also, predicate functions are generally expected to be free of side-effects.


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

...