使用 Kotlin Flow 测试 Android Room



我正在尝试测试一个RoomDAO 公开返回Flows函数。以下测试不会通过,我正在努力了解原因:

@Test
fun `observeHomeCoursesFeatured() does not return courses that are no longer featured`() = runBlocking {
val outputList: MutableList<List<HomeCourse>> = mutableListOf()
launch { subject.observeHomeCoursesFeatured().collect { outputList.add(it) } }
subject.saveHomeCoursesFeatured(listOf(getHomeCourseFeatured1(), getHomeCourseFeatured2()))
subject.saveHomeCoursesFeatured(listOf(getHomeCourseFeatured1()))
assertEquals(2, outputList.size)
assertEquals(listOf(getHomeCourseFeatured1(), getHomeCourseFeatured2()), outputList[0])
assertEquals(listOf(getHomeCourseFeatured1()), outputList[1])
}

assertEquals(2, outputList.size)outputList是空

的失败。此测试通过:

@Test
fun `observeHomeCoursesFeatured() does not return courses that are no longer featured`() = runBlocking {
subject.saveHomeCoursesFeatured(listOf(getHomeCourseFeatured1(), getHomeCourseFeatured2()))
assertEquals(listOf(getHomeCourseFeatured1(), getHomeCourseFeatured2()), subject.observeHomeCoursesFeatured().first())
subject.saveHomeCoursesFeatured(listOf(getHomeCourseFeatured1()))
assertEquals(listOf(getHomeCourseFeatured1()), subject.observeHomeCoursesFeatured().first())
}

第二次测试通过,表明我的 DAO 工作正常,更多的是测试线程和Room用来触发Flow更改的线程之间的线程和并发性问题。

我已经在测试中添加了@get:Rule val archRule = InstantTaskExecutorRule()。我还用这个构建我的测试数据库:

db = Room.inMemoryDatabaseBuilder(ctx, CoreDatabase::class.java)
.setTransactionExecutor(Executors.newSingleThreadExecutor())
.allowMainThreadQueries()
.build()

我错过了什么?

launch是异步的,因此您具有争用条件。

@Test
fun `observeHomeCoursesFeatured() does not return courses that are no longer featured`() = runBlocking {
val job = async { subject.observeHomeCoursesFeatured().take(2).toList() }
subject.saveHomeCoursesFeatured(listOf(getHomeCourseFeatured1(), getHomeCourseFeatured2()))
subject.saveHomeCoursesFeatured(listOf(getHomeCourseFeatured1()))
val outputList = job.await()
assertEquals(2, outputList.size)
assertEquals(listOf(getHomeCourseFeatured1(), getHomeCourseFeatured2()), outputList[0])
assertEquals(listOf(getHomeCourseFeatured1()), outputList[1])
}

对于这种情况,我建议使用 flow.first((

@Dao 
interface TreeDao{ 
@Query(Select * from tree) 
fun getTrees():Flow<List<Tree>>}
}

例如存储库

class Repository(context:Context){
db = Room.inMemoryDatabaseBuilder(context, TreeDatabase::class.java)
.build()
fun getTrees():Flow<List<Tree>>
}

因为任何流量都是无穷无尽的,而不是我们的测试,我们可以取流量的第一个值。

@Test
fun GetList()=runTest{
val list=repository.getDao().getTrees().first()
Assert.assertEqual(1,list.size)
}

最新更新