使用 Mockito 模拟 PreferenceManager

Mock PreferenceManager with Mockito

我是 Android 单元测试的新手,我想在现有项目中添加一些单元测试。我正在使用 MVP 设计架构。在我的演示者中,我调用 PreferenceManager 以获得默认值 SharedPrefences 但它总是 returns 为空。我在 Whosebug 上遵循了一些关于如何模拟 PreferenceManagerSharedPreferences 的教程和建议,但我无法让它工作。这是我的主持人class

@RunWith(MockitoJUnitRunner.class)
public class SettingsPresenterTest {
    @Mock
    private SettingsView mView;
    @Mock
    private LocalConfiguration conf;
    private SettingsPresenter mPresenter;

    public SettingsPresenterTest() {
        super();
    }

    @Before
    public void startUp() throws Exception {
        MockitoAnnotations.initMocks(LocalConfiguration.class);
        MockitoAnnotations.initMocks(PreferenceManager.class);


        mPresenter = new SettingsPresenter(mView);


        final SharedPreferences sharedPrefs = 
        Mockito.mock(SharedPreferences.class);
        final Context context = Mockito.mock(Context.class);

       Mockito.when(PreferenceManager.getDefaultSharedPreferences(context)).
       thenReturn(sharedPrefs);
    }


    @Test
    public void notificationsEnabledClicked() throws Exception {
        boolean notifsEnabled = false;
        mPresenter.notificationsEnabledClicked(notifsEnabled);

        Mockito.verify(mView).setNotificationsView(notifsEnabled);
    }
}

这里是 SharedPreferences 返回 null

的方法
public class LocalConfiguration { 
    public TerritoryDto getLastSavedTerritory() {
           SharedPreferences preferences = 
           PreferenceManager.getDefaultSharedPreferences(H.getContext());
           String terrritoryString = preferences.getString(SAVED_TERRITORY, 
           null);
           return 
           SerializerHelper.getInstance().deserialize(terrritoryString, 
           TerritoryDto.class);
    }
}

你能给我一些解决这个错误的指导吗?

与其直接引用 Android SDK,不如从演示者逻辑中抽象出来。这意味着,不是执行 PreferenceManager.getDefaultSharedPreferences(),而是创建一个抽象并从您的抽象中请求 territoryString

这会给你带来什么,就是你的演示者不会知道来自 Android SDK 的 PreferenceManagerSharedPreferences 的前缀,因此你会有足够的接缝来执行纯单元测试。

说到这里,让我们来实现抽象。已声明以下接口:


    public interface Storage {
        @Nullable
        String getSavedTerritory();
    }

具体实现为:


    public SharedPrefsStorage implements Storage {

        private final SharedPreferences prefs;

        public SharedPrefsStorage(Context context) {
            prefs = PreferenceManager.getDefaultSharedPreferences();
        }

        @Nullable
        @Override
        public String getSavedTerritory() {
            return prefs.getString(SAVED_TERRITORY, null);
        }

    }

那么你的presenter就会变成这样:


    public class LocalConfiguration { 

        final Storage storage;

        public LocalConfiguration(Storage storage) {
            this.storage = storage;
        }

        public TerritoryDto getLastSavedTerritory() {
               final String territory = storage.getSavedTerritory();

               return SerializerHelper.getInstance().deserialize(territory, TerritoryDto.class);
        }
    }

这将为您提供执行纯单元测试的接缝:


    @Test
    void someTest() {
        when(storage.getSavedTerritory()).thenReturn("New York");
        ...
    }

再也不用担心嘲笑PreferenceManager了。