Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Test SharedPreferences in Android

I am coming into a legacy codebase which uses SharedPreferences for data persistence. I'd like to test saving/retrieving a value, mocking using MockK. However, the assertion in this unit test never passes. It is as if the SharedPrefs aren't stored properly in testing:

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())
}}

Anybody know how to unit test SharedPrefs?

like image 219
IgorGanapolsky Avatar asked Dec 14 '22 11:12

IgorGanapolsky


1 Answers

You need Robolectric library to test classes related to the Context. This library will simulate an Android device(without emulator).
In that case, you can use RuntimeEnvironment.application.getApplicationContext() which will return real, not mocked object of Context class.

update as of May 2020:

RuntimeEnvironment.application.getApplicationContext() is now Deprecated.

please use ApplicationProvider.getApplicationContext() to get the Context. also, keep in mind that you should add testImplementation 'androidx.test:core:1.2.0' to your build.gradle.

so Espresso can help you as well, but it is instrumental tests though.

like image 90
samaromku Avatar answered Dec 27 '22 12:12

samaromku