Androidx 数据存储测试:确保您仅为此文件创建单个数据存储实例

And*_*rew 6 android sharedpreferences

目前,我正在为我的原始数据存储编写一些测试。我在这里遇到的唯一问题是我无法调用特定函数,因为这样我的测试就会失败/崩溃。我发现这非常令人困惑,因为我的所有其他功能似乎都有效,除了resetDatastore

这是我的代码:

存储库

private companion object {
    private const val SHOP_FILTER_PRODUCT_DATASTORE: String = "shop_filter_product_datastore_test"
    private const val SHOP_FILTER_LIST_DATASTORE: String = "shop_filter_list_datastore_test"
    private const val SHOP_FILTER_BTN_DATASTORE: String = "shop_filter_btn_datastore_test"
}

private val testNonVolatileProductDataStore = context.createDataStore(
    fileName = SHOP_FILTER_PRODUCT_DATASTORE,
    serializer = ShopFilterProductSerializer
)

private val testNonVolatileListDataStore = context.createDataStore(
    fileName = SHOP_FILTER_LIST_DATASTORE,
    serializer = ShopFilterListSerializer
)

private val testNonVolatileBtnDataStore = context.createDataStore(
    fileName = SHOP_FILTER_BTN_DATASTORE,
    serializer = ShopFilterBtnSerializer
)

override suspend fun setValueProduct(newProduct: ShopFilterTempHolder) {
    if (newProduct.id == null || newProduct.mQuery == null) return
    testNonVolatileProductDataStore.updateData { preferences ->
        preferences.toBuilder().apply {
            positionId = newProduct.id!!
            query = newProduct.mQuery
        }.build()
    }
}

override suspend fun setValueList(newList: ShopFilterTempHolder) {
    if (newList.id == null || newList.mQuery == null) return
    testNonVolatileListDataStore.updateData { preferences ->
        preferences.toBuilder().apply {
            positionId = newList.id!!
            query = newList.mQuery
            mQueryDirection = newList.mQueryDirection
        }.build()
    }
}

override suspend fun setShopFilterBtn(value: Boolean) {
    testNonVolatileBtnDataStore.updateData { preferences ->
        preferences.toBuilder().apply {
            isChecked = value
        }.build()
    }
}

override suspend fun peekProductValue(): ShopFilterTempHolder {
    val temp = shopFilterProduct.first()
    return ShopFilterTempHolder(temp.positionId, temp.query)
}

override suspend fun peekListValue(): ShopFilterTempHolder {
    val temp = shopFilterList.first()
    return ShopFilterTempHolder(temp.positionId, temp.query, temp.mQueryDirection)
}

override suspend fun peekBtnValue(): Boolean = mappedShopFilterBtn.first()

override suspend fun resetDatastore() {
    testNonVolatileProductDataStore.updateData { preferences ->
        preferences.toBuilder().apply {
            positionId = Constants.SHOP_FILTER_DEFAULT_PRODUCT_ID
            query = Constants.SHOP_FILTER_DEFAULT_PRODUCT_QUERY
        }.build()
    }
    testNonVolatileListDataStore.updateData { preferences ->
        preferences.toBuilder().apply {
            positionId = Constants.SHOP_FILTER_DEFAULT_LIST_ID
            query = Constants.SHOP_FILTER_DEFAULT_LIST_QUERY
            mQueryDirection = Constants.SHOP_FILTER_DEFAULT_LIST_QUERY_DIRECTION
        }.build()
    }
    testNonVolatileBtnDataStore.updateData { preferences ->
        preferences.toBuilder().apply {
            isChecked = true
        }.build()
    }
}
Run Code Online (Sandbox Code Playgroud)

测试

@Test
fun `values should be set to default`() = runBlocking {
    val newBtn =  false
    val newList =  ShopFilterTempHolder(0, "testString", 0)
    val newProduct =  ShopFilterTempHolder(0, "testString", 0)

    shopFilterValidator.tempBtnFilterValue = newBtn
    shopFilterValidator.tempListFilter = newList
    shopFilterValidator.tempProductFilter = newProduct

    shopFilterValidator.setNewBtnFilter()
    shopFilterValidator.setNewListFilter()
    shopFilterValidator.setNewProductFilter()

    assertEquals(newProduct, shopFilterDataStoreRepository.peekProductValue())
    assertEquals(newList, shopFilterDataStoreRepository.peekListValue())
    assertEquals(newBtn, shopFilterDataStoreRepository.peekBtnValue())

    shopFilterValidator.deleteAllValues()

    assertEquals(defautTempProductFilter, shopFilterDataStoreRepository.peekProductValue())
    assertEquals(defaultTempListFilter, shopFilterDataStoreRepository.peekListValue())
    assertEquals(defaultTempBtnFilterValue, shopFilterDataStoreRepository.peekBtnValue())
}
Run Code Online (Sandbox Code Playgroud)

堆栈跟踪

Exception in thread "DefaultDispatcher-worker-2 @coroutine#5" java.io.IOException: Unable to rename C:\Users\Censored\AppData\Local\Temp\robolectric-Method_values_should_be_set_to_default1366629743868428403\com.example.app-dataDir\files\datastore\shop_filter_product_datastore_test.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:303)
    at androidx.datastore.core.SingleProcessDataStore.transformAndWrite(SingleProcessDataStore.kt:280)
    at androidx.datastore.core.SingleProcessDataStore$actor$1.invokeSuspend(SingleProcessDataStore.kt:165)
    (Coroutine boundary)
    at kotlinx.coroutines.CompletableDeferredImpl.await(CompletableDeferred.kt:86)
    at androidx.datastore.core.SingleProcessDataStore$updateData$2.invokeSuspend(SingleProcessDataStore.kt:96)
    at androidx.datastore.core.SingleProcessDataStore.updateData(SingleProcessDataStore.kt:96)
    at com.example.app.repository.FakeDataStoreRepositoryImpl.deleteDataStore(FakeDataStoreRepositoryImpl.kt:86)
    at com.example.app.data.models.validator.ShopFilterValidator$deleteAllValues$1.invokeSuspend(ShopFilterValidator.kt:80)
Run Code Online (Sandbox Code Playgroud)

小智 3

不确定这是否可以帮助您,但就我而言,在 Windows 计算机上运行测试时出现问题,而在切换到 Linux 或在模拟器上执行测试时则不存在该问题