单元测试中getSharedPreferences返回null?Kotlin场景下的问题求助
首先直接回答你的核心问题:完全可以在测试类中通过SharedPreferenceHandler.mInstance.accessToken!!获取accessToken,但你当前的实现因为依赖未初始化的Application单例,导致测试时抛出异常,需要先重构代码来解决这个问题。
问题根源
你的SharedPreferenceHandler单例在类加载阶段就会初始化,而初始化过程依赖Application.mInstance——在Android测试环境中,Application对象不会自动初始化,所以Application.mInstance是null,调用getSharedPreferences时自然会抛出IllegalStateException。
重构SharedPreferenceHandler,适配测试场景
我们需要修改单例的实现,消除对Application单例的硬依赖,同时允许测试时注入自定义的SharedPreferences实例:
class SharedPreferenceHandler(private val sharedPreferences: SharedPreferences) { companion object { @Volatile private var mInstance: SharedPreferenceHandler? = null // 允许传入SharedPreferences,测试时可以传Mock对象 fun getInstance(sharedPrefs: SharedPreferences? = null): SharedPreferenceHandler { return mInstance ?: synchronized(this) { val prefs = sharedPrefs ?: run { checkNotNull(Application.mInstance) { "Application instance must be initialized first!" }.getSharedPreferences("myApp", Context.MODE_PRIVATE) } SharedPreferenceHandler(prefs).also { mInstance = it } } } } var accessToken: String? get() = sharedPreferences.getString(SharedPreference.ACCESS_TOKEN.name, null) set(token) = sharedPreferences.edit() .putString(SharedPreference.ACCESS_TOKEN.name, token) .apply() }
调整测试代码,注入Mock的SharedPreferences
用Mockito创建Mock的SharedPreferences,然后通过getInstance注入,这样就能控制accessToken的返回值,同时避免依赖Application:
@Test public void reload() { // 创建Mock的SharedPreferences SharedPreferences mockPrefs = Mockito.mock(SharedPreferences.class); // 预设accessToken的返回值 when(mockPrefs.getString(SharedPreference.ACCESS_TOKEN.name, null)) .thenReturn("234234234234234"); // 初始化单例时传入Mock对象 SharedPreferenceHandler.getInstance(mockPrefs); // 执行测试方法 presenter.reload(viewModel); // 此时你可以直接获取accessToken String token = SharedPreferenceHandler.getInstance().accessToken; assertNotNull(token); assertEquals("234234234234234", token); }
额外说明
如果你的测试框架是JUnit 5或者用了AndroidX Test,也可以考虑用ApplicationProvider.getApplicationContext()来获取测试环境的Context,再创建真实的SharedPreferences实例,但Mock方式更灵活,适合单元测试场景。
内容的提问来源于stack exchange,提问作者azsoftco
相关产品推荐
相关产品推荐

