我正在尝试测试我的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
)
}