首页 > 解决方案 > Room 的 DAO 方法返回 Flowable 的订阅者不会收到有关插入实体的通知

问题描述

我有一个带有一个实体和 DAO 的 Room 数据库,它允许插入对象并将SELECT查询作为Flowable. 当我订阅它Flowable,然后将一个新对象插入数据库时​​,不会产生新的结果。

@Database(entities = [User::class], version = 1)
abstract class TestDatabase : RoomDatabase() {
    abstract val dao: UserDao
}

@Dao
interface UserDao {
    @Insert
    fun insert(user: User)

    @Query("SELECT * FROM User")
    fun observeUsers(): Flowable<List<User>>
}

@Entity
data class User(@PrimaryKey val id: Int, val name: String)

失败的测试:

@RunWith(AndroidJUnit4::class)
class ObserveUsersTest {

    @Test
    fun observeUsersTest() {
        val db = Room.inMemoryDatabaseBuilder(
            InstrumentationRegistry.getContext(), TestDatabase::class.java
        ).build()
        val dao = db.dao
        val user = User(0, "George")
        val test = dao.observeUsers().test()

        dao.insert(user)
        test.assertValue(listOf(user))

        db.close()
    }
}

失败:

java.lang.AssertionError: Expected: [User(id=0, name=George)] (class: SingletonList), Actual: [] (latch = 1, values = 0, errors = 0, completions = 0)

如果在调用 to 之前完成插入,则测试通过observeUsers

    dao.insert(user)
    dao.observeUsers().test().assertValue(listOf(user))

我究竟做错了什么?

标签: androidrx-java2android-room

解决方案


我猜你没有等待足够长的时间来观察插入的结果。如果insert在内部是异步的(即使您没有使用 RxJava API 定义它),您可能会过早地订阅和测试单个值。

awaitCount在断言单个值之前尝试使用测试方法(因为你有一个无限的Flowable,所以awaitTerminalEvent当然不起作用):

dao.observeUsers()
.test()
.awaitCount(1, TestWaitStrategy.SLEEP_10MS, 5000)
.assertValue(listOf(user));

推荐阅读