I have a method of a data source class that makes the following call to a Shared Preferences extension:
override suspend fun removePendingBatch() {
preferences.remove(pendingBatchKey)
}
preferences is an instance of Shared Preferences
I need to do an unit test using mockk that checks if when calling this method of my data source class the call to this shared preferences extension is made.
In my test scenario I instantiate my preferences object like this:
private val preferences: SharedPreferences = mockk()
This is my unit test:
@Test
fun `when removePendingBatch() is called then remove from preferences`() = runBlockingTest {
every { preferences.remove(PENDING_BATCH_KEY) } just runs
batchDataSource.removePendingBatch()
verify(exactly = 1) { preferences.remove(PENDING_BATCH_KEY) }
}
The problem happens when I try to run this unit test, a mockk error saying there is no mock response is thrown:
no answer found for: Editor(child of #1#3).commit()
io.mockk.MockKException: no answer found for: Editor(child of #1#3).commit()
at io.mockk.impl.stub.MockKStub.defaultAnswer(MockKStub.kt:90)
at io.mockk.impl.stub.MockKStub.answer(MockKStub.kt:42)
at io.mockk.impl.recording.states.AnsweringState.call(AnsweringState.kt:16)
at io.mockk.impl.recording.CommonCallRecorder.call(CommonCallRecorder.kt:53)
at io.mockk.impl.stub.MockKStub.handleInvocation(MockKStub.kt:263)
...
I imagine that I should mock the editor method call inside the shared preferences, however it seems to me that the mockk can't do that very well with the just runs
statement, because when trying to do it the following syntax error appears:
I managed to solve this problem by mocking the commit
method coming from the SharedPreferences.Editor
object by this way:
every { preferences.edit().commit() } returns RandomUtils.nextBoolean()
In this case, just return any boolean, so we can mock the "remove" method, my complete test looks like this:
@Test
fun `when removePendingBatch() is called then remove from preferences`() = runBlockingTest {
every { preferences.edit().commit() } returns RandomUtils.nextBoolean()
every { preferences.remove(PENDING_BATCH_KEY) } just runs
batchDataSource.removePendingBatch()
verify(exactly = 1) { preferences.remove(PENDING_BATCH_KEY) }
}