【问题标题】:How to unit test SharedFlow on Android如何在 Android 上对 SharedFlow 进行单元测试
【发布时间】:2021-03-24 11:27:42
【问题描述】:

我有一个具有以下属性的 android viewmodel 类

private val _trainingNavigationEvents = MutableSharedFlow<NavigationEventTraining>(replay = 0)
    val trainingNavigationEvents = _trainingNavigationEvents.asSharedFlow()

fun navigate(navigationEvent: NavigationEventTraining) {
        viewModelScope.launch {
            _trainingNavigationEvents.emit(navigationEvent)
        }
    }

我正在使用 SharedFlow,因为它解决了 SingleLiveEvent 问题。

当我尝试对代码进行单元测试时,问题就出现了。我看不出如何使用涡轮机(或提供的原语)使其工作。

    @ExperimentalTime
    @Test
    fun `navigate`() = runBlockingTest {
        viewModel.handleIntent(TrainingViewModel.TrainingIntent.ShowQuestions)

        viewModel.navigationEvents.test {
            assertEquals(
                TrainingViewModel.TrainingNavigationEvent.NavigateToQuestions::class,
                expectItem()::class
            )
            cancelAndConsumeRemainingEvents()
        }
    }

我明白了

kotlinx.coroutines.TimeoutCancellationException: Timed out waiting for 1000 ms

我知道 SharedFlow 永远不会完成,这可能是部分原因,但我无法找到任何示例来说明如何执行此操作。

我正在使用 Junit 5 并且正在使用 TestCoroutineDispatcher 类扩展。

【问题讨论】:

标签: android unit-testing kotlin-coroutines kotlin-flow


【解决方案1】:

在 Turbine 的文档中有一个 Hot Flows 部分,我认为我们可以这样做:

@ExperimentalTime
@Test
fun `navigate`() = runBlockingTest {
    viewModel.navigationEvents.test {
        viewModel.handleIntent(TrainingViewModel.TrainingIntent.ShowQuestions)
        assertEquals(
            TrainingViewModel.TrainingNavigationEvent.NavigateToQuestions::class,
            expectItem()::class
        )
        cancelAndConsumeRemainingEvents()
    }
}

在 Turbine 的 .test { 块内移动扳机

【讨论】:

    【解决方案2】:

    我发布了类似的question,但我的问题是如何改进 Stateflow 测试。

    我认为问题在于您需要在测试中调用 ViewModel 初始化。

    例如:

     @ExperimentalTime
        @Test
        fun `navigate`() = runBlockingTest {
            viewModel = ViewModel(...)
            viewModel.handleIntent(TrainingViewModel.TrainingIntent.ShowQuestions)
    
            viewModel.navigationEvents.test {
                assertEquals(
                    TrainingViewModel.TrainingNavigationEvent.NavigateToQuestions::class,
                    expectItem()::class
                )
                cancelAndConsumeRemainingEvents()
            }
        }
    

    【讨论】:

      猜你喜欢
      • 2020-09-25
      • 2022-11-17
      • 2016-12-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-02-23
      • 1970-01-01
      相关资源
      最近更新 更多