在测试Room时,无法从LiveData中获取价值

问题描述 投票:0回答:0

我正在尝试测试我的Room Database,并按照架构组件示例GitHub应用中推荐的那样,使用这个函数对发出的LiveData进行观察。

注意:我从表中得到的是一个关系类而不是标准的实体。一一关系对象。虽然这个调用在设备上运行应用程序时可以工作。

我知道我在这里错过了一些愚蠢的细节。如果你能给我指出来,那就太好了。

fun <T> LiveData<T>.getOrAwaitValue(
    time: Long = 2,
    timeUnit: TimeUnit = TimeUnit.SECONDS
//    afterObserve: () -> Unit = {}
): T {
    var data: T? = null
    val latch = CountDownLatch(1)
    val observer = object : Observer<T> {
        override fun onChanged(o: T?) {
            data = o
            latch.countDown()
            [email protected](this)
        }
    }
    this.observeForever(observer)

//    afterObserve.invoke()

    // Don't wait indefinitely if the LiveData is not set.
    if (!latch.await(time, timeUnit)) {
        this.removeObserver(observer)
        throw TimeoutException("LiveData value was never set.")
    }

    @Suppress("UNCHECKED_CAST")
    return data as T
}

但是我得到的错误是说我不能在后台线程上访问数据。我可以通过使用coroutines在主线程上运行它来解决这个问题,但是这个 实时数据 不返回一个值,并且保持为空,这将导致TimeOutException。

这是我的测试方法

@Test
    //    @Throws(Exception::class)
    fun writeBagAndItemAssociation() = runBlocking {
        var bag1 = BagItem(bagId = 1, bagName = "AT", bagColor = 0)
        var bag2 = BagItem(bagId = 2, bagName = "Kamiliant", bagColor = 0)
        bagItemDao.insert(bag1)
        bagItemDao.insert(bag2)

        bag1 = bagItemDao.findItemsByName(bag1.bagName)[0]
        bag2 = bagItemDao.findItemsByName(bag2.bagName)[0]

        var item = InventoryItem(itemId = 1, itemName = "Blazer", bagOwnerId = bag2.bagId)
        inventoryItemDao.insert(item)
        CoroutineScope(Dispatchers.Main).launch {
            item = inventoryItemDao.findItemsByName("Blazer").getOrAwaitValue()[0]
            assertNotNull(item)
        }

        val itemsInBag2 =
            bagItemDao.getItemsAndBagsInBagWithId(id = bag2.bagId)
        assertEquals(1, itemsInBag2?.items?.size)

        val itemsInBag1 =
            bagItemDao.getItemsAndBagsInBagWithId(id = bag1.bagId)
        assertEquals(0, itemsInBag1?.items?.size)


//        val allItemsWithBag =
//            inventoryItemDao.getItemsWithBag().getOrAwaitValue()
//        assertThat(allItemsWithBag.size, `is`(1))
//        assertEquals(1, allItemsWithBag.size)
    }

ItemInventoryDao.kt

@Dao
interface InventoryItemDao : BaseDao<InventoryItem> {

    /**
     * Selects and returns the row that matches the supplied start time, which is our key.
     *
     * @param key startTimeMilli to match
     */
    @Query("SELECT * from my_inventory_table WHERE itemId = :key")
    fun get(key: Long): InventoryItem?

    /**
     * Deletes all values from the table.
     *
     * This does not delete the table, only its contents.
     */
    @Query("DELETE FROM my_inventory_table")
    fun clear()

    @Query("DELETE FROM my_inventory_table WHERE itemId =:itemId")
    fun delete(itemId: Long)

    //    @Transaction
    @Query("SELECT * FROM my_inventory_table")
    fun getItemsWithBag(): LiveData<List<ItemWithBag>>

    @Entity
    data class ItemWithBag(
        @Embedded val item: InventoryItem,
        @Relation(
            parentColumn = "bagOwnerId",
            entityColumn = "bagId"
        )
        val bag: BagItem
    )
}

android android-room android-livedata kotlin-coroutines
© www.soinside.com 2019 - 2024. All rights reserved.