question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

MockitoJUnitRunner causes NPE when using @Mock on MockedStatic fields

See original GitHub issue

check that

  • 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

Versions:

  • mockito: 3.4.4
  • junit: 4.12
  • jdk: 1.8
  • os: windows 10

Example:

  1. MockitoJUnitRunnerWithMockedStaticTest
    • Reproduces the problem documented in this issue.
  2. MockitoOpenMocksMockedStaticTest
    • Same tests but manually opens and closes the mocks (doesn’t use the runner). Shows the tests are ran as expected.

Problem:

The MockitoJUnitRunner is causing a NullPointerException when the test class contains a @Mock instance field with a type of MockedStatic. This exception only occurs for tests that are ran after a prior test fails. If all the tests pass, there are no issues.

Stack Trace (Test 1):

java.lang.AssertionError: intentional failure
	at org.junit.Assert.fail(Assert.java:88)
	at org.mockito.example.MockitoJUnitRunnerWithMockedStaticTest.testName1(MockitoJUnitRunnerWithMockedStaticTest.java:40)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
	at org.mockito.internal.runners.DefaultInternalRunner$1$1.evaluate(DefaultInternalRunner.java:54)
	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
	at org.mockito.internal.runners.DefaultInternalRunner$1.run(DefaultInternalRunner.java:99)
	at org.mockito.internal.runners.DefaultInternalRunner.run(DefaultInternalRunner.java:105)
	at org.mockito.internal.runners.StrictRunner.run(StrictRunner.java:40)
	at org.mockito.junit.MockitoJUnitRunner.run(MockitoJUnitRunner.java:163)
	at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
	at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:538)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:760)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:460)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:206)

org.mockito.exceptions.misusing.NotAMockException: Argument passed to Mockito.mockingDetails() should be a mock, but is an instance of class java.lang.Class!
	at org.mockito.internal.runners.DefaultInternalRunner$1$2.testFinished(DefaultInternalRunner.java:81)
	at org.junit.runner.notification.SynchronizedRunListener.testFinished(SynchronizedRunListener.java:56)
	at org.junit.runner.notification.RunNotifier$7.notifyListener(RunNotifier.java:190)
	at org.junit.runner.notification.RunNotifier$SafeNotifier.run(RunNotifier.java:72)
	at org.junit.runner.notification.RunNotifier.fireTestFinished(RunNotifier.java:187)
	at org.junit.internal.runners.model.EachTestNotifier.fireTestFinished(EachTestNotifier.java:38)
	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:331)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
	at org.mockito.internal.runners.DefaultInternalRunner$1.run(DefaultInternalRunner.java:99)
	at org.mockito.internal.runners.DefaultInternalRunner.run(DefaultInternalRunner.java:105)
	at org.mockito.internal.runners.StrictRunner.run(StrictRunner.java:40)
	at org.mockito.junit.MockitoJUnitRunner.run(MockitoJUnitRunner.java:163)
	at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
	at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:538)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:760)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:460)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:206)

Stack Trace (Test 2):

java.lang.NullPointerException
	at org.mockito.example.MockitoJUnitRunnerWithMockedStaticTest.testName2(MockitoJUnitRunnerWithMockedStaticTest.java:54)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
	at org.mockito.internal.runners.DefaultInternalRunner$1$1.evaluate(DefaultInternalRunner.java:54)
	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
	at org.mockito.internal.runners.DefaultInternalRunner$1.run(DefaultInternalRunner.java:99)
	at org.mockito.internal.runners.DefaultInternalRunner.run(DefaultInternalRunner.java:105)
	at org.mockito.internal.runners.StrictRunner.run(StrictRunner.java:40)
	at org.mockito.junit.MockitoJUnitRunner.run(MockitoJUnitRunner.java:163)
	at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
	at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:538)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:760)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:460)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:206)

Investigation:

After some investigation, it appears the first test is failing twice (once in the test and once in the testFinished listener). This code:

https://github.com/mockito/mockito/blob/573bf0df389964d7fdeb4de486882d4599b8033c/src/main/java/org/mockito/internal/runners/DefaultInternalRunner.java#L75-L96

Line 81 is where it fails the second time. If we navigate down the call hierarchy, it appears it fails because the static mock has already been cleaned up so the framework doesn’t think it’s a mock and fails with a NotAMockException. Since it fails there, it doesn’t set the listener to null which will in-turn result in the mocks not being initialized on the next test that’s ran (hits line 51):

https://github.com/mockito/mockito/blob/573bf0df389964d7fdeb4de486882d4599b8033c/src/main/java/org/mockito/internal/runners/DefaultInternalRunner.java#L42-L59

Since the mocks are not initialized for the second test, it ultimately causes the NullPointerException.

It’s also causing the remaining tests after the first test failure to bounce back and forth between NullPointerException and NotAMockException. The reason for this appears to be because this failure object never gets reset after it’s processed so it keeps restarting the chain of throwing the two exceptions back and forth.

Also, I did include a sample test that manually opens and closes the mocks (doesn’t use MockitoJUnitRunner) and everything is working as expected. Using the try-with-resource works fine as well.

I did investigate further and noticed something related to this might have been addressed in this PR. It only updated the findStubbings method to skip the static mocks, though. Was the AllInvocationsFinder.find(…) method intentional left out of that or just an oversight?

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:8 (4 by maintainers)

github_iconTop GitHub Comments

1reaction
raphwcommented, Aug 4, 2020

Perfect, Gradle does not work with snapshot versions, happened to me a few times, too.

0reactions
Cybermitecommented, Aug 4, 2020

Okay, sorry for the confusion. When I was investigating this issue on July 25, I must have installed into locally and it got shoved into my local .m2 repo as 3.4.6 without the fix. Then when you fixed it and I updated the pom version to point to 3.4.6 it didn’t redownload it because it was already in my local repo.

I deleted it from my local .m2 repo and redownloaded it from maven-central. Everything is good now. Thanks!

Read more comments on GitHub >

github_iconTop Results From Across the Web

Mockito - NullpointerException when stubbing Method
For me the reason I was getting NPE is that I was using Mockito.any() when mocking primitives. I found that by switching to...
Read more >
Mocking Static Methods With Mockito - Baeldung
Why? First, a class depending on a static method has tight coupling, and second, it nearly always leads to code that is difficult...
Read more >
Mockito (Mockito 4.9.0 API) - javadoc.io
Minimizes repetitive mock creation code. Makes the test class more readable. Makes the verification error easier to read because the field name is...
Read more >
Bump mockito-core from 2.28.2 to 3.4.6 - The Mail Archive
... <li>MockitoJUnitRunner causes NPE when using <a href="https://github.com/Mock";>@Mock</a> on MockedStatic fields [(<a ...
Read more >
Mocking Static Methods With Mockito: Explained With Examples
Nowadays, using Mockito to mock static methods is very easy. First, make sure to import the org.mockito.MockedStatic; namespace. When declaring ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found