使用Mockito模拟PreferenceManager

时间:2017-10-23 09:47:42

标签: android unit-testing junit mockito tdd

我是Android单元测试的新手,我想在现有项目中添加一些单元测试。我正在使用MVP设计架构。在我的演示者中,我调用了PreferenceManager以获取默认的SharedPrefences,但它始终返回null。我已经在stackoverflow上关注了如何模拟PreferenceManagerSharedPreferences的一些教程和建议,但我无法使其工作。这是我的演讲者课程

@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);
    }
}

您能否就如何解决此错误给我一些指导?

1 个答案:

答案 0 :(得分:2)

不是直接引用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);
        }

    }

然后你的主持人就会变成这样:


    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