4

我正在进入一个使用 SharedPreferences 进行数据持久性的遗留代码库。我想测试保存/检索一个值,使用MockK进行模拟。但是,此单元测试中的断言永远不会通过。就好像 SharedPrefs 在测试中没有正确存储:

class MyProfilePrefsTest {
  private lateinit var myProfilePrefs: ProfilePrefs
  @RelaxedMockK private lateinit var mockSharedPrefs: SharedPreferences
  @RelaxedMockK private lateinit var context: Context

  @Before
  fun setup() {
    MockKAnnotations.init(this)

    val sharedPreferences = mockk<SharedPreferences>()
    every { sharedPreferences.edit() } returns (mockk())
    myProfilePrefs = ProfilePrefs(context, sharedPreferences)

    mockStatic(DeviceInfo::class)
    every { DeviceInfo.serialNumber() } returns "fake_serial"
}

@Test
fun `Saving correct cellular download pref for device id`() {
    // Arrange
    val isEnabled = true

    // Act
    myProfilePrefs.setCellularDownloadingEnabled(isEnabled)

    // Assert
    assertTrue(myProfilePrefs.getCellularDownloadingEnabled())
}}

有人知道如何对 SharedPrefs 进行单元测试吗?

4

2 回答 2

6

感谢@samaromku 上面建议的答案。这是完整的解决方案。它使用AndroidX 测试运行器

@RunWith(AndroidJUnit4::class)
class ProfilePrefsTest {
  private lateinit var profilePrefs: ProfilePrefs
  private lateinit var context: Context

  @Before
  fun setup() {
    context = getApplicationContext<MyApplication>()
    val sharedPreferences = context.getSharedPreferences(
        "prefs",
        MODE_PRIVATE
    );
    profilePrefs = ProfilePrefs(context, sharedPreferences)

    mockStatic(DeviceInfo::class)
    every { DeviceInfo.serialNumber() } returns FAKE_SERIAL_NUMBER
  }

  @Test
  fun `Saving correct cellular download pref for device id`() {
    // Arrange
    val isEnabled = true

    // Act
    profilePrefs.setCellularDownloadingEnabled(isEnabled)

    // Assert
    assertTrue(profilePrefs.isCellularDownloadingEnabled())
}

}

于 2019-07-22T19:25:34.160 回答
6

您需要Robolectric库来测试与Context. 这个库将模拟一个 Android 设备(没有模拟器)。
在这种情况下,您可以使用RuntimeEnvironment.application.getApplicationContext()which 将返回真实的,而不是模拟的Context类对象。

截至 2020 年 5 月的更新:

RuntimeEnvironment.application.getApplicationContext()现在已弃用

请使用ApplicationProvider.getApplicationContext()获取Context. 另外,请记住,您应该添加testImplementation 'androidx.test:core:1.2.0'到您的build.gradle.

所以 Espresso也可以帮助你,但它是工具测试。

于 2019-07-22T18:10:20.960 回答