Тестирование с участием MutableSharedFlow - java.lang.IllegalStateException: это задание еще не завершено

Приносим извинения за вопрос, который, вероятно, является очень любительским. Я начинаю разбираться с потоками и испытываю проблемы с тестированием, когда дело касается MutableSharedFlow.

Ниже приводится простейший пример, который я могу построить, воссоздающий проблему:

@ExperimentalCoroutinesApi
@ExperimentalTime
class MyExampleTest {

    val testDispatcher: TestCoroutineDispatcher = TestCoroutineDispatcher()

    @Test
    fun test() = testDispatcher.runBlockingTest  {
        val sharedFlow = MutableSharedFlow<String>()

        sharedFlow.take(2).collect {
            println(it)
        }

        sharedFlow.tryEmit("Hello")
        sharedFlow.tryEmit("World")
    }
}

Это приводит к следующей ошибке:

java.lang.IllegalStateException: This job has not completed yet

    at kotlinx.coroutines.JobSupport.getCompletionExceptionOrNull(JobSupport.kt:1187)
    at kotlinx.coroutines.test.TestBuildersKt.runBlockingTest(TestBuilders.kt:53)
    at kotlinx.coroutines.test.TestBuildersKt.runBlockingTest(TestBuilders.kt:80)
    at com.example.MyExampleTest.test(MyExampleTest.kt:22)

Исходя из моего ограниченного понимания, я думаю, что это как-то связано с тем, что SharedFlow никогда не завершается. Но я думал, что наличие take(2) смягчит это. Мы ценим любые предложения!


person SamCosta1    schedule 13.02.2021    source источник


Ответы (1)


Исходя из моего ограниченного понимания, я думаю, что это как-то связано с тем фактом, что SharedFlow никогда не завершается.

Вы правы, это более-менее проблема. Поток основан на сопрограммах, и сопрограмма еще не завершена.

На мой взгляд, лучший способ модульного тестирования Flows - это Turbine:

https://github.com/cashapp/turbine

// Cold Flow
flowOf("one", "two").test {
  assertEquals("one", expectItem())
  assertEquals("two", expectItem())
  expectComplete()
}

// Hot Flow
MutableStateFlow("test").test {
    assertThat(expectItem()).isEqualTo("test")
    cancelAndConsumeRemainingEvents()
}

Есть также нерешенная проблема, связанная с этой конкретной проблемой:

https://github.com/Kotlin/kotlinx.coroutines/issues/1204

person shredder    schedule 18.02.2021
comment
Это отлично работает с холодными потоками, но по-прежнему возникают аналогичные проблемы с горячими :( - person SamCosta1; 23.02.2021
comment
Я обновил свой ответ, включив в него тест горячего потока - person shredder; 24.02.2021