android / android/codelab-android-datastore

"multiple instances" error when removing value during unit testing

Open
#48 7 comments 8 reactions 0 assignees View on GitHub
Dominant language
Kotlin
Stars
240
Forks
113
PR merge metrics
No merged PRs in 30d

Description

When trying to remove some key from datastore-preferences during unittest I'm getting an error about "multiple instances" of the datastore.
The following code reproduces the problem:

`
import android.content.Context
import androidx.datastore.core.DataStore
import androidx.datastore.preferences.core.PreferenceDataStoreFactory
import androidx.datastore.preferences.core.Preferences
import androidx.datastore.preferences.core.edit
import androidx.datastore.preferences.core.stringPreferencesKey
import androidx.datastore.preferences.preferencesDataStoreFile
import androidx.test.core.app.ApplicationProvider
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.SupervisorJob
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import org.robolectric.RobolectricTestRunner

@ExperimentalCoroutinesApi
@RunWith(RobolectricTestRunner::class)
class TestDataStore {

companion object {
private val DATASTORE_KEY = stringPreferencesKey("DATASTORE_KEY")
}

@get:Rule
val testCoroutineRule = TestCoroutineRule()

private lateinit var dataStore: DataStore

@Before
fun setup() {
val context = ApplicationProvider.getApplicationContext()
dataStore =
PreferenceDataStoreFactory.create(
scope = CoroutineScope(testCoroutineRule.testCoroutineDispatcher + SupervisorJob())
) {
context.preferencesDataStoreFile("preferences")
}
}

@Test
fun test() {
testCoroutineRule.runBlockingTest {
dataStore.edit { it[DATASTORE_KEY] = "team" }

dataStore.edit { it.remove(DATASTORE_KEY) }
}
}
}
`

The stacktrace:

`Unable to rename C:\Users\Cassio\AppData\Local\Temp\robolectric-Method_test8095984772844777287\com.nautiluslog.data.test-dataDir\files\datastore\preferences.preferences_pb.tmp.This likely means that there are multiple instances of DataStore for this file. Ensure that you are only creating a single instance of datastore for this file.
java.io.IOException: Unable to rename C:\Users\Cassio\AppData\Local\Temp\robolectric-Method_test8095984772844777287\com.nautiluslog.data.test-dataDir\files\datastore\preferences.preferences_pb.tmp.This likely means that there are multiple instances of DataStore for this file. Ensure that you are only creating a single instance of datastore for this file.
at androidx.datastore.core.SingleProcessDataStore.writeData$datastore_core(SingleProcessDataStore.kt:433)
at androidx.datastore.core.SingleProcessDataStore.transformAndWrite(SingleProcessDataStore.kt:410)
at androidx.datastore.core.SingleProcessDataStore.handleUpdate(SingleProcessDataStore.kt:276)
at androidx.datastore.core.SingleProcessDataStore.access$handleUpdate(SingleProcessDataStore.kt:76)
at androidx.datastore.core.SingleProcessDataStore$actor$3.invokeSuspend(SingleProcessDataStore.kt:242)
at androidx.datastore.core.SingleProcessDataStore$actor$3.invoke(SingleProcessDataStore.kt)
at androidx.datastore.core.SingleProcessDataStore$actor$3.invoke(SingleProcessDataStore.kt)
at androidx.datastore.core.SimpleActor$offer$2.invokeSuspend(SimpleActor.kt:122)
(Coroutine boundary)
at com.nautiluslog.data.repository.TestDataStore$test$1.invokeSuspend(TestDataStore.kt:54)
at com.nautiluslog.testutils.TestCoroutineRule$runBlockingTest$1.invokeSuspend(TestCoroutineRule.kt:30)
at kotlinx.coroutines.test.TestBuildersKt$runBlockingTest$deferred$1.invokeSuspend(TestBuilders.kt:50)`

Contributor guide

Open the contributing guide

Research direction

Start by running the reproducer in TestDataStore.kt, especially the setup and two dataStore.edit calls, using the TestCoroutineRule from TestCoroutineRule.kt. Read the SingleProcessDataStore.kt stack-trace locations to understand the failed write and rename; done means the test can remove DATASTORE_KEY without the multiple-instances or rename error.

Written by the indexing model from the issue text.

Assessment

Tech stack
android, kotlin
Domain
database, mobile
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.