【问题标题】:Testing Android Room with Kotlin Flow使用 Kotlin Flow 测试 Android Room
【发布时间】:2020-06-27 23:28:53
【问题描述】:

我正在尝试测试一个 Room DAO 公开返回 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()

我错过了什么?

【问题讨论】:

    标签: android kotlin android-room kotlin-coroutines kotlin-flow


    【解决方案1】:

    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])
    }
    

    【讨论】:

    • 现在我的测试将无法完成,因为runBlocking { subject.observeHomeCoursesFeatured().collect { outputList.add(it) } } 无休止地运行。这很正常,这就是为什么我认为我必须使用launch启动协程@
    • 是一样的。我的测试不会结束,因为join() 等待协程完成而它自己不会因为我在 Room 生成的永无止境的Flow 上调用collect()
    • 没有意识到这是一个永无止境的Flow。另一个更新。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-05
    • 2018-06-06
    • 1970-01-01
    • 2017-10-19
    相关资源
    最近更新 更多