Prashant
Prashant

Reputation: 943

Mockito NullPointerException while using any

I am trying to use Mockito like this :

    Mockito.when(Mockito.any(ObjectMapper.class).readValue(Mockito.any(BufferedReader.class),Mockito.any(Class.class))).thenReturn(new Person("1","abc"));

This is from Jackson library .

public <T> T readValue(Reader src, Class<T> valueType)

The reason I am doing it is because the time I reach this point of the code there are a ton of objects which were created. Mocking on every step would take time.

Any reason why I am getting NPE when code reaches this mockito statement?

Stack Trace :

java.lang.NullPointerException
    at com.prashant.flax.ShellTest.givenDirectoryHasFiles(ShellTest.java:139)
    at com.prashant.flax.ShellTest.testExecute(ShellTest.java:61)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.rules.ExternalResource$1.evaluate(ExternalResource.java:48)
    at org.junit.rules.RunRules.evaluate(RunRules.java:20)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:160)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:78)
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:212)
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:68)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140)

As you can see it is in a given method(this method only has this piece of code) , so I can see while debugging, it reaches over there and crashes.

Upvotes: 16

Views: 25984

Answers (3)

Guillermo
Guillermo

Reputation: 791

For me the actual problem was that I was trying to mock a spy. When mocking a spy you have to use the doReturn or doAnswer methods. Otherwise the method of the spy will be actually called while trying to mock it and unexpected behavior can happen. E.g. when calling when with any(), any() will just return null. So it is likely that you will get an NullPointerException.

Here is a full example that demonstrates the bahavior:

package com.company;

import org.junit.Test;

import static org.junit.Assert.assertEquals;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.*;

public class SpyTest {

    public class Controller {
        public String method(String arg) {
            return arg.substring(0, 1);
        }
    }

    @Test
    public void withMockTest() {
        Controller controllerMocked = mock(Controller.class);
        when(controllerMocked.method(anyString())).thenReturn("42");
        assertEquals("42", controllerMocked.method("FOO"));
    }

    @Test(expected = NullPointerException.class)
    public void withSpyWhenThenReturnBreakingBecauseMethodToBeMockedIsActuallyBeingCalled() {
        Controller controllerSpied = spy(new Controller());
        when(controllerSpied.method(any())).thenReturn("42");
    }

    @Test
    public void withSpyDoReturnWhen() {
        Controller controllerSpied = spy(new Controller());
        doReturn("42").when(controllerSpied).method(any());
        assertEquals("42", controllerSpied.method("FOO"));
    }

}

Upvotes: 2

VIN
VIN

Reputation: 6957

To extend on what @jeff-bowman said in his answer, any() returns null, so if you need something that doesn't return null, you can try this:

/**
 * never returns null
 */
private inline fun <reified T> any(type: Class<T>): T = Mockito.any(type)

/**
 * returns null
 */
private inline fun <reified T> any(): T = Mockito.any<T>()

Upvotes: 2

Jeff Bowman
Jeff Bowman

Reputation: 95704

As Oliver mentioned in the comments, you can't apply when to happen to all objects. Mockito works via subclassing, so you have to create a mock instance using mock, spy, or a @Mock or @Spy annotation; customize the behavior; and then install the mock using dependency injection or other similar tricks.


As to why this happens, the return value for any() actually is null; matchers like any are only supposed to be used as arguments to when and verify, and Mockito can't produce a specialized instance of Class that represents "any Class", so Mockito returns a dummy value (null) and stores data on a specialized stack of argument matchers. Though Mockito has better error messages to alert you to this situation, your code NPEs before Mockito can give you a proper exception with usage examples.

For more about matcher return values and the stack, see my other SO answer on "How do Mockito matchers work?".

Upvotes: 14

Related Questions