【问题标题】:Coroutine Unit Testing Fails for the Class类的协程单元测试失败
【发布时间】:2019-07-28 09:23:28
【问题描述】:

我在对协程进行单元测试时遇到了一个奇怪的问题。该类有两个测试,单独运行时,它们都通过了,当我运行完整的测试类时,一个失败并出现断言错误。 我正在使用MainCoroutineRule 来使用TestCoroutineScope 并依赖于最新的协程测试库 这是测试:

    @Test
    fun testHomeIsLoadedWithShowsAndFavorites() {
        runBlocking {
            // Stubbing network and repository calls
            whenever(tvMazeApi.getCurrentSchedule("US", currentDate))
                .thenReturn(getFakeEpisodeList())
            whenever(favoriteShowsRepository.allFavoriteShowIds())
                .thenReturn(arrayListOf(1, 2))
        }

        mainCoroutineRule.runBlockingTest {
            // call home viewmodel
            homeViewModel.onScreenCreated()
            // Check if loader is shown
            assertThat(LiveDataTestUtil.getValue(homeViewModel.getHomeViewState())).isEqualTo(Loading)
            // Observe on home view state live data
            val homeViewState = LiveDataTestUtil.getValue(homeViewModel.getHomeViewState())
            // Check for success data
            assertThat(homeViewState is Success).isTrue()
            val homeViewData = (homeViewState as Success).homeViewData
            assertThat(homeViewData.episodes).isNotEmpty()
            // compare the response with fake list
            assertThat(homeViewData.episodes).hasSize(getFakeEpisodeList().size)
            // compare the data and also order
            assertThat(homeViewData.episodes).containsExactlyElementsIn(getFakeEpisodeViewDataList(true)).inOrder()
        }
    }

另一个测试几乎与测试没有收藏夹的节目类似。我正在尝试将HomeViewModel 方法测试为:

        homeViewStateLiveData.value = Loading
        val coroutineExceptionHandler = CoroutineExceptionHandler { _, exception ->
            onError(exception)
        }

        viewModelScope.launch(coroutineExceptionHandler) {
            // Get shows from network and favorites from room db on background thread
            val favoriteShowsWithFavorites = withContext(Dispatchers.IO) {
                val favoriteShowIds = favoriteShowsRepository.allFavoriteShowIds()
                val episodes = tvMazeApi.getCurrentSchedule(COUNTRY_US, currentDate)
                getShowsWithFavorites(episodes, favoriteShowIds)
            }
            // Return the combined result on main thread
            withContext(Dispatchers.Main) {
                onSuccess(favoriteShowsWithFavorites)
            }
        }
    }

我无法找到单独运行的测试通过以及测试完整类时其中一个失败的实际原因。如果我遗漏了什么,请帮忙

【问题讨论】:

    标签: android unit-testing kotlin-coroutines


    【解决方案1】:

    Coroutine 附带的 Retrofit 和 Room 支持拥有挂起功能,并自行将它们移出 UI 线程。因此,它们大大减少了开发人员处理线程回调的麻烦。最初,我通过Dispatchers.IO 明确地将网络和数据库的挂起调用移动到IO。这是不必要的,并且还会导致不必要的上下文切换,从而导致不稳定的测试。由于库会自动执行此操作,因此只需在可用时将数据处理回 UI。

            viewModelScope.launch(coroutineExceptionHandler) {
                // Get favorite shows from db, suspend function in room will launch a new coroutine with IO dispatcher
                val favoriteShowIds = favoriteShowsRepository.allFavoriteShowIds()
                // Get shows from network, suspend function in retrofit will launch a new coroutine with IO dispatcher
                val episodes = tvMazeApi.getCurrentSchedule(COUNTRY_US, currentDate)
    
                // Return the result on main thread via Dispatchers.Main
                homeViewStateLiveData.value = Success(HomeViewData(getShowsWithFavorites(episodes, favoriteShowIds)))
            }
    

    【讨论】:

    • 您能否链接说明上下文切换是在这些库内部完成的文档?真的很感激。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-13
    相关资源
    最近更新 更多