我正在使用 koltin 的
mockk
框架编写一个测试类用于数据存储。班级看起来像
`open class MyStorageClass(context: Context) : Storage {
private val testDataStore = context.dataStore
private val dataException: suspend FlowCollector<Preferences>.(cause: Throwable) -> Unit = { exception ->
when (exception) {
is IOException -> emit(emptyPreferences())
else -> throw exception
}
}
override suspend fun <T> getPreferenceFlow(key: Preferences.Key<T>, defaultValue: T): Flow<T> =
testDataStore.data
.catch(dataException)
.map { preferences ->
preferences[key] ?: defaultValue
.also { Timber.d("Got preference : ${key.name} : $it") }
}
}`
存储界面的样子
`interface Storage {
suspend fun <T> getPreferenceFlow(key: Preferences.Key<T>, defaultValue: T): Flow<T>
}`
kotlin中使用
mockk
的测试类写为
`class HnavStorageTest {
private lateinit var dataStore: DataStore<Preferences>
lateinit var preferences: Preferences
lateinit var mockContext: Context
lateinit var sut: HnavStorage
@Before
fun setup() {
MockKAnnotations.init(this, true)
dataStore = mockk(relaxed = true)
preferences = mockk(relaxed = true)
mockContext = mockk(relaxed = true)
sut = HnavStorage(mockContext)
}
@Test
fun `test getPreference Flow`() = runBlocking {
coEvery { dataStore.data } returns flowOf(preferences)
val key: Preferences.Key<String> = stringPreferencesKey(name = "test_key")
val defaultValue = "test_value"
val expectedValue = "mocked_value"
every { preferences[key] } returns expectedValue
val flow = sut.getPreferenceFlow(key, defaultValue)
var result: String? = null
flow.collect {
result = it
}
assert(result == expectedValue)
verify { Timber.d("Get preference value: ${key.name} : $expectedValue") }
}
}`
运行测试类后,我收到错误如下
`Cannot invoke "String.isEmpty()" because "parent.path" is null
java.lang.NullPointerException: Cannot invoke "String.isEmpty()" because "parent.path" is null
at java.base/java.io.File.<init>(File.java:364)
at androidx.datastore.DataStoreFile.dataStoreFile(DataStoreFile.kt:36)
at androidx.datastore.preferences.PreferenceDataStoreFile.preferencesDataStoreFile(PreferenceDataStoreFile.kt:38)
at androidx.datastore.preferences.PreferenceDataStoreSingletonDelegate$getValue$1$1.invoke(PreferenceDataStoreDelegate.kt:107)
at androidx.datastore.preferences.PreferenceDataStoreSingletonDelegate$getValue$1$1.invoke(PreferenceDataStoreDelegate.kt:106)
at androidx.datastore.preferences.core.PreferenceDataStoreFactory$create$delegate$1.invoke(PreferenceDataStoreFactory.kt:69)`
如何解决这个问题?任何帮助将不胜感激
我尝试模拟首选项,检查异常但找不到它
您需要定义
mockContext.dataStore
将与 every
返回的内容。如果 mockContext.dataStore
是扩展属性,请使用 mockkStatic(Context::dataStore)
使其可模拟。
@Before
fun setup() {
MockKAnnotations.init(this, true)
dataStore = mockk(relaxed = true)
preferences = mockk(relaxed = true)
mockContext = mockk(relaxed = true)
mockkStatic(Context::dataStore)
every { mockContext.dataStore } returns dataStore
sut = HnavStorage(mockContext)
}
@After
fun tearDown() {
unmockkAll()
}