Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
237 views
in Technique[技术] by (71.8m points)

android - Androidx datastore test: Ensure that you are only creating a single instance of datastore for this file

Currently, I am writing some test for my proto datastore. The only problem I have here is that I can't call a specific function because then my test fails / crashes. I find this very confusing, because all my other functions seem to work, except resetDatastore

Here is my code:

Repository

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

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

Stacktrace

Exception in thread "DefaultDispatcher-worker-2 @coroutine#5" java.io.IOException: Unable to rename C:UsersCensoredAppDataLocalTemp
obolectric-Method_values_should_be_set_to_default1366629743868428403com.example.app-dataDirfilesdatastoreshop_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)
question from:https://stackoverflow.com/questions/65853645/androidx-datastore-test-ensure-that-you-are-only-creating-a-single-instance-of

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)
Waitting for answers

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...