1

我有以下代码:

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.UncompletedCoroutinesError: 测试以活动作业完成: ["coroutine#2":ActorCoroutine{Active}@31b46ea7]

这是有道理的,因为数据存储区可能会使用后台任务,但是我如何使用 android 数据存储区测试类?

我还在谷歌问题跟踪器中问了这个问题: 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
    }
}

但是我应该能够使用一个使用数据存储的类,而无需将其作为构造函数参数注入

4

1 回答 1

1

谷歌的人回答了我。

这里有一个测试示例

主要思想是创建与封闭测试范围不同的范围,然后将其取消

所以

runBlockingTest {
  val dataStoreScope = TestCoroutineScope(TestCoroutineDispatcher() + Job())

  val feature = Feature(dataStoreScope)
  <put your test code here>
  dataStoreScope.cancel()
  dataStoreScope.cleanupTestCoroutines()
}

datastoreScope 创建和 datastoreScope.cleanupTestCoroutines 可以放在 @Before 和 @After 函数中。

他们告诉我他们正在为以后的版本制定更好的解决方案

于 2021-01-21T07:17:30.447 回答