Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Method Only.verify throws NullPointerException #3237

Open
5 tasks done
ilia-sretenskii opened this issue Jan 17, 2024 · 0 comments
Open
5 tasks done

Method Only.verify throws NullPointerException #3237

ilia-sretenskii opened this issue Jan 17, 2024 · 0 comments

Comments

@ilia-sretenskii
Copy link

ilia-sretenskii commented Jan 17, 2024

Method Only.verify throws NullPointerException with the latest mockito-core 5.9.0

Here is a sample code in Kotlin which triggers this issue.

verify(service, only()).doSomething()

It triggers the following NullPointerException to be thrown.

java.lang.NullPointerException: Cannot invoke "org.mockito.invocation.Invocation.getMock()" because "undesired" is null
	at org.mockito.internal.exceptions.Reporter.noMoreInteractionsWanted(Reporter.java:555)
	at org.mockito.internal.verification.Only.verify(Only.java:30)
	at org.mockito.internal.verification.MockAwareVerificationMode.verify(MockAwareVerificationMode.java:30)
	at org.mockito.internal.handler.MockHandlerImpl.handle(MockHandlerImpl.java:75)
	at org.mockito.internal.handler.NullResultGuardian.handle(NullResultGuardian.java:29)
	at org.mockito.internal.handler.InvocationNotifierHandler.handle(InvocationNotifierHandler.java:34)
	at org.mockito.internal.creation.bytebuddy.MockMethodInterceptor.doIntercept(MockMethodInterceptor.java:82)
	at org.mockito.internal.creation.bytebuddy.MockMethodAdvice.handle(MockMethodAdvice.java:134)

A quick analysis shows that it is caused by method Only.verify which searches for an optional unverified invocation by execution of method InvocationsFinder.findFirstUnverified, but then fails to check for the result for null and just calls method Reporter.noMoreInteractionsWanted which throws the exception because the invocation was not found.
https://github.com/mockito/mockito/blob/main/src/main/java/org/mockito/internal/verification/Only.java#L29C37-L30

        MatchableInvocation target = data.getTarget();
        List<Invocation> invocations = data.getAllInvocations();
        List<Invocation> chunk = findInvocations(invocations, target);
        if (invocations.size() != 1 && !chunk.isEmpty()) {
            Invocation unverified = findFirstUnverified(invocations);
            throw noMoreInteractionsWanted(unverified, (List) invocations);
        }

Note that there is method NoMoreInteractions.verify which also makes a call to the same two methods InvocationsFinder.findFirstUnverified and Reporter.noMoreInteractionsWanted but it does so properly, thus the exception can not be thrown there.
https://github.com/mockito/mockito/blob/main/src/main/java/org/mockito/internal/verification/NoMoreInteractions.java#L25-L28

        Invocation unverified = findFirstUnverified(data.getAllInvocations());
        if (unverified != null) {
            throw noMoreInteractionsWanted(unverified, (List) data.getAllInvocations());
        }

So I suggest that the same check for null would be made in method Only.verify to avoid the exception.
And I also suggest that static analysis based on annotations would be introduced, then it would be obvious that method findFirstUnverified returns a nullable value while method noMoreInteractionsWanted does not accept a nullable argument.

  • The mockito message in the stacktrace have useful information, but it didn't help
  • The problematic code (if that's possible) is copied here;
    Note that some configuration are impossible to mock via Mockito
  • Provide versions (mockito / jdk / os / any other relevant information)
  • Provide a Short, Self Contained, Correct (Compilable), Example of the issue
    (same as any question on stackoverflow.com)
  • Read the contributing guide
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant