Skip to content

Disabled Mock Triggers NPE when Checking isMock #3469

@Kramermp

Description

@Kramermp

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

There is the ability to trigger a NullPointerException by calling isMock on a disabled mock. This behavior should probably be changed to either return true, because a DisabledMock is still a mock or isMock should throw a DisabledMockException because you are interacting with a disabledMock.

Problematic Code is: DisabledMockHandler#getMockSettings returning null here breaks the logic for determining if an object a mock.

@Override
    public MockCreationSettings getMockSettings() {
        return null;
    }

NPE Source is in the following loop of MockUtil#getMockHandlerOrNull.

for (MockMaker mockMaker : mockMakers.values()) {
            MockHandler<?> handler = mockMaker.getHandler(mock);
            if (handler != null) {
                assert getMockMaker(handler.getMockSettings().getMockMaker()) == mockMaker;
                return handler;
            }
        }

Stack Trace Snippet:

java.lang.NullPointerException: Cannot invoke "org.mockito.mock.MockCreationSettings.getMockMaker()" because the return value of "org.mockito.invocation.MockHandler.getMockSettings()" is null
	at org.mockito.internal.util.MockUtil.getMockHandlerOrNull(MockUtil.java:160)
	at org.mockito.internal.util.MockUtil.isMock(MockUtil.java:147)
	at org.mockito.internal.util.DefaultMockingDetails.isMock(DefaultMockingDetails.java:32)
	at org.mockito.internal.framework.DefaultMockitoFrameworkTest.behavior_after_clear_inline_mocks_is_mock(DefaultMockitoFrameworkTest.java:226)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:569)

The following unit test reproduces the issue. This unit test can be added to DefaultMockitoFrameworkTest and will fail for an NPE. This test should probably be modeled to either trigger a DisabledMockException or return true because a DisabledMock is still a mock.


    @Test
    public void behavior_after_clear_inline_mocks_is_mock() {
        // clearing mocks only works with inline mocking
        assumeTrue(Plugins.getMockMaker() instanceof InlineMockMaker);
        PersonWithName obj = mock(PersonWithName.class);
        when(obj.getMyName()).thenReturn("Bob");
        assertEquals("Bob", obj.getMyName());
        assertTrue(mockingDetails(obj).isMock());
        framework.clearInlineMocks();

        try {
            mockingDetails(obj).isMock();
        } catch (DisabledMockException e) {
            return;
        }
        Assert.fail("Should have thrown DisabledMockException");
    }

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions