Mockito on Android, Context.getString(id) and NullPointerException

12,725

Solution 1

It seems that you are using the exact code from developer.android.com. Apparently they posted an incomplete example.. add this method to your test:

@Before
public void setup(){
   MockitoAnnotations.initMocks(this);
}

For further reference checkout Mockito's docs

Solution 2

This code should be the first line of Your test:

doReturn("Sample Hello world string")
            .when(mMockContext)
            .getString(any(Integer.class));

A stubbing of a method is needed

Share:
12,725
Derek K
Author by

Derek K

Updated on June 12, 2022

Comments

  • Derek K
    Derek K about 2 years

    I've just started learning a Mockito testing framework, I followed official tutorial from: developer.android.com

    The code is:

    private static final String FAKE_STRING = "HELLO WORLD";
    
    @Mock
    Context mMockContext;
    
    @Test
    public void readStringFromContext_LocalizedString() {
        // Given a mocked Context injected into the object under test...
        when(mMockContext.getString(R.string.hello_world))
                .thenReturn(FAKE_STRING);
        ClassUnderTest myObjectUnderTest = new ClassUnderTest(mMockContext);
    
        // ...when the string is returned from the object under test...
        String result = myObjectUnderTest.getHelloWorldString();
    
        // ...then the result should be the expected one.
        assertThat(result, is(FAKE_STRING));
    }
    

    I wrote following ClassUnderTest:

    public class ClassUnderTest {
    
    private Context context;
    
    public ClassUnderTest(Context context)
    {
        this.context=context;
    }
    
    public String getHelloWorldString()
    {
        return context.getString(R.string.hello_world);
    }
    

    }

    and after running I'm getting NullPointerException:

        java.lang.NullPointerException
    at android.content.Context.getHelloWorldString(Context.java:293)
    at com.darekk.draggablelistview.unit_tests.MockitoTest.readStringFromContext_LocalizedString(MockitoTest.java:46)
    at java.lang.reflect.Method.invokeNative(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:511)
    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.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.JUnit45AndHigherRunnerImpl.run(JUnit45AndHigherRunnerImpl.java:37)
    at org.mockito.runners.MockitoJUnitRunner.run(MockitoJUnitRunner.java:62)
    at org.junit.runners.Suite.runChild(Suite.java:128)
    at org.junit.runners.Suite.runChild(Suite.java:27)
    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.junit.runner.JUnitCore.run(JUnitCore.java:137)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:115)
    at android.support.test.internal.runner.TestExecutor.execute(TestExecutor.java:59)
    at android.support.test.runner.AndroidJUnitRunner.onStart(AndroidJUnitRunner.java:262)
    at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:1619)
    

    When I replace android Context with my own class it works.

    Platform: IntelliJ IDEA Community Edition 15.0.6

    I really appreciate any help.

  • Derek K
    Derek K about 8 years
    Hmm, should I put it inside getHelloWorldString() method? where exactly?, It's strange. I thought only Context.getString(...) should be stubbed.
  • R. Zagórski
    R. Zagórski about 8 years
    Edited my answer. No need to modify class under test.
  • Derek K
    Derek K about 8 years
    I have this: when(mMockContext.getString(R.string.hello_world)) .thenReturn(FAKE_STRING);
  • Derek K
    Derek K about 8 years
    I tried your solution, but any(Integer.class) cannot be resolved, so I used anyInt() instead and got another error: org.mockito.exceptions.misusing.InvalidUseOfMatchersExceptio‌​n: Invalid use of argument matchers! 0 matchers expected, 1 recorded:
  • R. Zagórski
    R. Zagórski about 8 years
    Yes, the reason there should be anyInt() is that you stub a method that has int parameter. You could pass any integer parameter and method call will be stubbed by Mockito.
  • R. Zagórski
    R. Zagórski about 8 years
    The last error is connected with incorrect assertThat call. With objects annotated with Mockito You can only check interactions with it (whether a method was invoked or not): verify(mMockContext).getString. It is a better test practice to create a real test model, rather than mock it. It's dependencies should be mocked.
  • Derek K
    Derek K about 8 years
    Ok, replaced assertThat() with verify(), and got: org.mockito.exceptions.misusing.WrongTypeOfReturnValue:Strin‌​g cannot be returned by getResources() getResources() should return Resources. If you know how to do it correctly, please edit your answer with complete working example.
  • ericn
    ericn almost 7 years
    There is no difference between your solution and what the poster already had when(mMockContext.getString(R.string.hello_world)).thenRetur‌​n(FAKE_STRING);
  • Alex
    Alex over 4 years
    This is incorrect. Per the Android documentation: "At runtime, [local unit] tests are executed against a modified version of android.jar where all final modifiers have been stripped off. This lets you use popular mocking libraries, like Mockito." See developer.android.com/studio/test/…