You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Junit测试SharedPreferences存储数据后断言失败问题排查求助

SharedPreference JUnit测试失败排查

核心错误点

  • 仅定义mock行为,未实际执行存储操作
    whenever(editor.putString(xxx))只是定义mock Editor对象调用putString时的返回值规则,不会真的执行存储逻辑,需要主动调用editor.putString()方法才会触发存储流程。
  • 存储的Key参数错误
    putString第一个参数传的是USER_PREFS(这是SharedPreference的配置文件名),但后续校验是否存在用的是USER_ID_KEY,两者不匹配,就算存成功也查询不到对应值。
  • 未提交编辑结果
    调用putString后必须主动调用apply()/commit()才能将修改同步到SharedPreference中,原代码没有执行提交操作。
  • mock对象未定义contains方法的返回规则(若使用纯Mockito mock)
    如果用的是Mockito mock出来的userPrefs对象,没有为userPrefs.contains(USER_ID_KEY)打桩的话,该方法默认返回布尔类型默认值false,也会导致断言失败。这类状态读写场景更推荐使用AndroidX测试库提供的真实可读写的SharedPreferences实现,而非全mock。

修复代码示例

推荐方案:使用真实测试用SharedPreference

@Test
fun `when store user then load user`() {
    // 使用AndroidX测试库提供的真实可读写SharedPreferences实例
    val userPrefs = SharedPreferences.Builder()
        .withName(USER_PREFS)
        .build()
    val editor = userPrefs.edit()
    val user = getUser()
    // 主动执行存储+提交操作
    editor.putString(USER_ID_KEY, user!!.userID)
    editor.apply()
    // 断言正常通过
    assert(userPrefs.contains(USER_ID_KEY))
}

兼容全mock场景方案

如果必须使用全mock验证调用流程,修复如下:

@Test
fun `when store user then load user`() {
    whenever(context.getSharedPreferences(USER_PREFS, Context.MODE_PRIVATE)).thenReturn(userPrefs)
    whenever(userPrefs.edit()).thenReturn(editor)
    whenever(editor.putString(anyString(), anyString())).thenReturn(editor)
    doNothing().`when`(editor).apply()
    // 为contains方法打桩模拟存储后的状态
    whenever(userPrefs.contains(USER_ID_KEY)).thenReturn(true)

    val user = getUser()
    // 主动执行存储+提交操作
    editor.putString(USER_ID_KEY, user!!.userID)
    editor.apply()
    
    assert(userPrefs.contains(USER_ID_KEY))
}

全mock方案无法验证真实的存储逻辑,仅能验证方法调用流程是否符合预期,不推荐用于读写逻辑校验。

内容的提问来源于stack exchange,提问作者VVB

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.28 06:06:02