【问题标题】:How to test a Loading Indicator with coroutines (TestCoroutineScope is deprecated)?如何使用协程测试加载指示器(不推荐使用 TestCoroutineScope)?
【发布时间】:2022-08-10 11:27:04
【问题描述】:

我正在关注this codelab,但它似乎已经过时了。 TestCoroutineScope 已弃用。

@ExperimentalCoroutinesApi
class MainCoroutineRule(val dispatcher: TestCoroutineDispatcher = TestCoroutineDispatcher()):
    TestWatcher(),
    TestCoroutineScope by TestCoroutineScope(dispatcher) {
    override fun starting(description: Description?) {
        super.starting(description)
        Dispatchers.setMain(dispatcher)
    }

    override fun finished(description: Description?) {
        super.finished(description)
        cleanupTestCoroutines()
        Dispatchers.resetMain()
    }
}

我一直在尝试重现以下测试

@Test
fun loadTasks_loading() {
    // Pause dispatcher so you can verify initial values.
    mainCoroutineRule.pauseDispatcher()

    // Load the task in the view model.
    statisticsViewModel.refresh()

    // Then assert that the progress indicator is shown.
    assertThat(statisticsViewModel.dataLoading.getOrAwaitValue(), `is`(true))

    // Execute pending coroutines actions.
    mainCoroutineRule.resumeDispatcher()

    // Then assert that the progress indicator is hidden.
    assertThat(statisticsViewModel.dataLoading.getOrAwaitValue(), `is`(false))
}

但我没有成功。我现在不知道如何暂停调度程序。

我怎样才能以新的方式做到这一点?

    标签: android unit-testing kotlin-coroutines


    【解决方案1】:

    如果您将鼠标悬停在已弃用的 TestCoroutineDispatcher 上,您应该会看到以下弹出窗口:

    @Deprecated("The execution order of TestCoroutineDispatcher can be confusing, and the mechanism of pausing is typically misunderstood. Please use StandardTestDispatcher or UnconfinedTestDispatcher instead.", level = DeprecationLevel.WARNING)

    所以这里的解决方案是使用StandardTestDispatcherUnconfinedTestDispatcher

    【讨论】:

    • 谢谢回复。我已经这样做了,但是没有方法可以暂停调度程序。你知道我该怎么做吗?
    • 我认为不再允许了,此链接显示了使用测试调度程序的迁移指南,我链接的部分显示了使用 pauseDispatcher github.com/Kotlin/kotlinx.coroutines/blob/master/… 时的迁移
    【解决方案2】:

    在这里找到答案:Migrating to the new coroutines 1.6 test APIs by Marton Braun

    @get:Rule
    val mainDispatcherRule = MainDispatcherRule()
    
    @Test
    fun loadTasks_loading() = runTest {
        // Main dispatcher will not run coroutines eagerly for this test
        Dispatchers.setMain(StandardTestDispatcher())
    
        // Load the task in the ViewModel
        statisticsViewModel.refresh()
    
        // Validate progress indicator is shown
        assertThat(statisticsViewModel.dataLoading.getOrAwaitValue()).isTrue()
    
        // Execute pending coroutine actions
        // Wait until coroutine in statisticsViewModel.refresh() complete 
        advanceUntilIdle()
    
        // Validate progress indicator is hidden
        assertThat(statisticsViewModel.dataLoading.getOrAwaitValue()).isFalse()
    }
    

    MainDispatcherRule

    @ExperimentalCoroutinesApi
    class MainDispatcherRule(
            val testDispatcher: TestDispatcher = UnconfinedTestDispatcher()
        ) : TestWatcher() {
    
        override fun starting(description: Description) {
            Dispatchers.setMain(testDispatcher)
        }
    
        override fun finished(description: Description) {
            Dispatchers.resetMain()
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-10-17
      • 1970-01-01
      • 2012-04-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-08-03
      相关资源
      最近更新 更多