使用 Mockito 在 Android 单元测试中模拟共享首选项时出错

Error in Mocking Shared Preference in Android Unit Test using Mockito

我正在尝试使用 Mockito 库通过模拟 Android 共享首选项来编写单元测试,但即使经过多次尝试,它对我也不起作用。请检查下面我的示例代码,让我知道它出了什么问题

我目前正在使用"JCAndKSolutions/android-unit-test" android junit插件。

我的代码如下:

PreferenceHelper.java

 public class PreferencesHelper
    {
         private SharedPreferences mSharedPreferences;

         static String PREFERENCE_USER;

         public PreferencesHelper(SharedPreferences mSharedPreferences)
        {
            this.mSharedPreferences = mSharedPreferences;
        }

        public void setUserName(String userName)
        {
            mSharedPreferences.edit().putString(PREFERENCE_USER,   "Vkc").apply();
        }

        public String getUserName()
        {
            return mSharedPreferences.getString(PREFERENCE_USER, null);

        }

    }


PreferenceHelperTest.java

public class PreferencesHelperTest extends TestCase
{
    @Mock
    SharedPreferences mSharedPreference;

    @Mock
    SharedPreferences.Editor mEditor;

    @Mock
    Context context;

    @Mock
    PreferenceManager mPreferenceManager;

    PreferencesHelper mPrefHelper;

    public void setUp() throws Exception
    {
        initMocks(this);
    }

    public void testSetUserName(){

        final InOrder inOrder = inOrder(mEditor);
        when(mSharedPreference.edit()).thenReturn(mEditor);
        mPrefHelper = new PreferencesHelper(mSharedPreference);

        mPrefHelper.setUserName("Grapes");
        inOrder.verify(mEditor).putString(PreferencesHelper.PREFERENCE_USER, "Grapes");
        inOrder.verify(mEditor).apply();
    }
}

如果我运行这个junit测试我得到以下错误

java.lang.NullPointerException
    at     com.example.aag.testhelloworld.PreferencesHelper.setUserName(PreferencesHelper.java:21)
    at     com.example.aag.testhelloworld.PreferencesHelperTest.testSetUserName(PreferencesHelperTest.java:43)
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.internal.runners.JUnit38ClassRunner.run(JUnit38ClassRunner.java:86)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:74)
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:211)
at     com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:67)
    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:134)

在调试时我发现当调用putString() 方法时会抛出nullPointer 异常。

哪里出错了有什么帮助或线索吗??

我认为问题在于,因为您正在模拟 Editor,当您调用 putString() 时,它会 return 一个不同的对象。也尝试模拟 putString() 方法,如下所示: when(mEditor.putString(anyString(), anyString())).thenReturn(mEditor);

这对我有用...

public MainPresenter(final MainView view, SharedPreferences sp) {
    this.view = view;
    this.sp = sp;
}

public void saveToSharedPref(String key,int value){
    SharedPreferences.Editor editor = sp.edit();
    editor.putInt(key,value);
}

//Tests

@Mock
MainPresenter.MainView view;
@Mock
SharedPreferences sp;
@Mock
SharedPreferences.Editor editor;

@Before
public void setup(){
    view = mock(MainPresenter.MainView.class);
    sp = mock(SharedPreferences.class);
    editor = mock(SharedPreferences.Editor.class);
    presenter = new MainPresenter(view, sp);

}

@Test
public void saveToSharedPref_withValidKeyAndValue_willSaveDataToSharedPreference(){

    when(sp.edit()).thenReturn(editor);
    presenter.saveToSharedPref("my_key",10);
    verify(editor,times(1)).putInt(any(String.class), any(Integer.class));
}