#android #kotlin #kotlin-coroutines #android-jetpack-datastore
#Android #kotlin #kotlin-сопрограммы #android-jetpack-хранилище данных
Вопрос:
У меня есть следующий код:
class Feature(scope:CoroutineScope = CoroutineScope(Dispatchers.IO)){
val dataStore: DataStore<MetaDataStore> = context.createDataStore(
fileName = PREFERENCES,
serializer = MetadataSerializer,
scope = scope
)
fun foo() {
}
}
При тестировании класса я хочу проверить функцию foo
runBlockingTest {
val feature = Feature(this)
feature.foo()
verifyStuff...
}
Важно использовать TestCoroutineScope, поскольку это гарантирует мне, что любой асинхронный материал был завершен
К сожалению, я получаю сообщение об ошибке:
kotlinx.coroutines.test.Ошибка незавершенной сопрограммы: тест завершен с активными заданиями: [«сопрограмма #2»: ActorCoroutine{Active}@31b46ea7]
Это имеет смысл, поскольку хранилище данных может использовать фоновые задачи, но тогда как мне протестировать классы с помощью хранилища данных Android?
Я также задал вопрос в Google issue tracker: https://issuetracker.google.com/issues/177856517
Тем временем я поддержал некоторую фиктивную реализацию и внедрил ее в конструктор.
import androidx.datastore.core.DataStore
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
class DatastoreInmemoryImpl<T>(defaultValue:T) : DataStore<T> {
val sharedFlow = MutableStateFlow(defaultValue)
val mutex = Mutex()
override val data: Flow<T> = sharedFlow.asStateFlow()
override suspend fun updateData(transform: suspend (t: T) -> T): T = mutex.withLock {
sharedFlow.value = transform.invoke(sharedFlow.value)
sharedFlow.value
}
}
Но я должен иметь возможность использовать класс, использующий хранилище данных, без необходимости вводить его в качестве параметра конструктора
Ответ №1:
Ребята из Google ответили мне.
Основная идея состоит в том, чтобы создать область, отличную от области тестирования, и впоследствии отменить ее
итак
runBlockingTest {
val dataStoreScope = TestCoroutineScope(TestCoroutineDispatcher() Job())
val feature = Feature(dataStoreScope)
<put your test code here>
dataStoreScope.cancel()
dataStoreScope.cleanupTestCoroutines()
}
Создание хранилища данных и datastoreScope.cleanupTestCoroutines можно поместить в функции @Before и @After.
Они сказали мне, что работают над лучшим решением для более поздней версии
Комментарии:
1. ссылка мертва, извините.