-
-
Notifications
You must be signed in to change notification settings - Fork 2.6k
Description
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