【问题标题】:Androidx datastore test: Ensure that you are only creating a single instance of datastore for this fileAndroidx 数据存储测试:确保您只为此文件创建一个数据存储实例
【发布时间】:2021-01-22 22:35:08
【问题描述】:

目前,我正在为我的原型数据存储编写一些测试。我在这里遇到的唯一问题是我无法调用特定函数,因为那时我的测试失败/崩溃。我觉得这很令人困惑,因为我的所有其他功能似乎都可以工作,除了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()
    }
}

测试

@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())
}

堆栈跟踪

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)

【问题讨论】:

标签: android sharedpreferences


【解决方案1】:

不确定这是否可以帮助您,但在我的情况下,问题发生在 Windows 机器上运行测试时,而在切换到 Linux 或在模拟器上执行测试时不存在

【讨论】:

  • 嗯,为单个测试切换操作系统可能不是最好的解决方案,对吧?
  • 我不会称之为解决方案。只是想指出问题可能与平台有关
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-07-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-19
  • 2016-10-16
相关资源
最近更新 更多