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

NullPointerException when calling methods on spy of a final class with JDK > 11 #2202

Closed
JanMosigItemis opened this issue Feb 12, 2021 · 2 comments

Comments

@JanMosigItemis
Copy link
Contributor

JanMosigItemis commented Feb 12, 2021

Hi there,

I may have encountered a bug in mockito-inline with respect to spies of final classes. You may want to checkout this demo project: https://github.com/JanMosigItemis/mockito.inline.spy.bug

I have:

  • Windows 10.0.19042.804
  • Git Bash 2.30.0.windows.2
  • Maven 3.6.3
  • Surefire 3.0.0-M5
  • Mockito-Inline 3.7.7
  • JUnit 5.7.0
  • -Dnet.bytebuddy.experimental=true
  • mock-maker-inline

The following test runs into an NPE:

import org.junit.jupiter.api.Test;
import org.mockito.Mockito;

import java.lang.reflect.Method;

/**
 * Unit test for simple App.
 */
public class AppTest {
    @Test
    public void test_something() throws Exception {
        Method realMethod = getClass().getMethod("some_method");
        Method spyMethod = Mockito.spy(realMethod);
        spyMethod.invoke(this); // <- NPE
    }

    public void some_method() {

    }
}

I cannot pin point the exact cause of the NPE from the logs / stack traces. The NPE only happens when running a maven build with JDK >11. I tested with JDK12 and 15 (same result for both). However, the test runs successfully with JDK 11. Using a mock instead of a spy works on all JDKs.

Also running the test from within Eclipse (4.18.0) works when running Eclipse with JDK11 and does not work when running with JDK > 11.

Stacktrace is like this:

java.lang.NullPointerException
	at java.base/java.util.Objects.requireNonNull(Objects.java:208)
	at java.base/jdk.internal.reflect.Reflection.verifyMemberAccess(Reflection.java:127)
	at java.base/java.lang.reflect.AccessibleObject.slowVerifyAccess(AccessibleObject.java:734)
	at java.base/java.lang.reflect.AccessibleObject.verifyAccess(AccessibleObject.java:720)
	at java.base/java.lang.reflect.AccessibleObject.checkAccess(AccessibleObject.java:692)
	at java.base/java.lang.reflect.Method.invoke(Method.java:556)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:64)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:554)
	at de.itemis.mosig.mockito.inline.spy.bug.AppTest.test_something(AppTest.java:16)

Any thoughts on this?

@TimvdLippe
Copy link
Contributor

java.lang.reflect.Method is one of the building blocks of Mockito and therefore we can't guarantee correctness when mocking/spying such classes. Instead, we recommend using real objects. For more information, please see the full discussion in #2026 (comment) This will likely be addressed in #1833 to notify users when they run into these kind of situations.

@JanMosigItemis
Copy link
Contributor Author

Thank you very much. I did not know that creating a spy will change the behavior of all instances of that type.

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

2 participants