使用 Mockito 和 Android 模拟一个 Drawable

Mock a Drawable with Mockito and Android

如何模拟 Drawable?我试过这段代码。它还没有编译:

@Test
public void readStringFromContext_LocalizedString() {
    Simulation myObjectUnderTest = new Simulation();
    when(mActivity.getResources().getDrawable(R.mipmap.dungeon)).thenReturn(Resources.getSystem()));
    when(mWorld.defaultPlace()).thenReturn(new Place("blaha", mActivity.getResources().getDrawable(R.mipmap.dungeon)));
    WalkingPerson myObjectUnderTest2 = new WalkingPerson(myObjectUnderTest, mock(AdventureWorld.class), "blaha", 2, mActivity);
    String result2 = myObjectUnderTest2.getHelloWorldString();
    assertThat(result2, is(FAKE_STRING));
}

我不知道如何模拟可绘制对象。问题是这个语句

when(mActivity.getResources().getDrawable(R.mipmap.dungeon)).thenReturn(Resources.getSystem()));

我也试试下面的

package dev.game.adventure;

import static junit.framework.Assert.assertEquals;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.CoreMatchers.*;
import static org.mockito.Mockito.*;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.CoreMatchers.*;
import static org.mockito.Mockito.*;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;

import android.content.SharedPreferences;

import java.util.Calendar;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.res.AssetManager;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.support.test.InstrumentationRegistry;
import android.util.DisplayMetrics;

@RunWith(MockitoJUnitRunner.class)
public class AdventureTest {

    private static final String FAKE_STRING = "HELLO WORLD";

    @Mock
    Simulation engine;

    @Mock
    AdventureWorld mWorld;

    @Mock
    FullscreenActivity mActivity;

    @Mock
    Drawable mDrawable;


    @Test
    public void readStringFromContext_LocalizedString() {
        Simulation myObjectUnderTest = new Simulation();
        when(mActivity.getResources().getDrawable(R.mipmap.dungeon)).thenReturn(mDrawable);
        when(mWorld.defaultPlace()).thenReturn(new Place("blaha", mActivity.getResources().getDrawable(R.mipmap.dungeon)));
        WalkingPerson myObjectUnderTest2 = new WalkingPerson(myObjectUnderTest, mock(AdventureWorld.class), "blaha", 2, mActivity);
        String result2 = myObjectUnderTest2.getHelloWorldString();
        assertThat(result2, is(FAKE_STRING));
    }


    @Test
    public void useAppContext() throws Exception {
        // Context of the app under test.
        Context appContext = InstrumentationRegistry.getTargetContext();
        assertEquals("dev.game.adventure", appContext.getPackageName());

    }


}

但是我得到这个错误

java.lang.NullPointerException: Attempt to invoke virtual method 'android.graphics.drawable.Drawable android.content.res.Resources.getDrawable(int)' on a null object reference
at dev.game.adventure.AdventureTest.readStringFromContext_LocalizedString(AdventureTest.java:53)
at java.lang.reflect.Method.invoke(Native Method)
at org.junit.runners.model.FrameworkMethod.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.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access[=13=]0(ParentRunner.java:58)
at org.junit.runners.ParentRunner.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.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access[=13=]0(ParentRunner.java:58)
at org.junit.runners.ParentRunner.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:58)
at android.support.test.runner.AndroidJUnitRunner.onStart(AndroidJUnitRunner.java:375)
at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:2074)

更新。它仍然不起作用。我只是在浪费时间。

package dev.game.adventure;

import static junit.framework.Assert.assertEquals;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.CoreMatchers.*;
import static org.mockito.Mockito.*;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.CoreMatchers.*;
import static org.mockito.Mockito.*;

import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;

import android.content.SharedPreferences;

import java.util.Calendar;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.res.AssetManager;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.support.test.InstrumentationRegistry;
import android.util.DisplayMetrics;

@RunWith(MockitoJUnitRunner.class)
public class AdventureTest {

    private static final String FAKE_STRING = "HELLO WORLD";

    @Mock
    Simulation engine;

    @Mock
    AdventureWorld mWorld;

    @Mock
    FullscreenActivity mActivity;

    @Mock
    Drawable mDrawable;


    @Mock
    Resources mResources;


    @Mock
    Place mPlace;

    @Test
   // @Ignore
    public void readStringFromCowntext_LocalizedString() {
        Simulation myObjectUnderTest = new Simulation();
        when(mResources.getDrawable(R.mipmap.dungeon)).thenReturn(mDrawable);
        when(mActivity.getResources()).thenReturn(mResources);
        when(mActivity.getResources().getDrawable(R.mipmap.dungeon)).thenReturn(mDrawable);
        when(mWorld.defaultPlace()).thenReturn(mPlace);
        WalkingPerson myObjectUnderTest2 = new WalkingPerson(myObjectUnderTest, mock(AdventureWorld.class), "blaha", 2, mActivity);
        String result2 = myObjectUnderTest2.getHelloWorldString();
        assertThat(result2, is(FAKE_STRING));
    }


    @Test
    public void useAppContext() throws Exception {
        // Context of the app under test.
        Context appContext = InstrumentationRegistry.getTargetContext();
        assertEquals("dev.game.adventure", appContext.getPackageName());

    }


}

您模拟了 mActivity,但没有指定在此模拟上调用 getResources() 方法时应该发生什么。因此这个方法returns null 而你运行进入了NPE。

为了让它工作,您还需要 return getResources() 方法的模拟对象。

希望对您有所帮助。