Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Testing involving MutableSharedFlow - java.lang.IllegalStateException: This job has not completed yet

Apologies for what is probably a very amateur question. I'm getting to grips with flows and having issues with testing where MutableSharedFlow is concerned.

The following is the simplest example I can construct that recreates the problem:

@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")
    }
}

This results int he following error:

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)

From my limited understanding I think it's something to do with the fact that SharedFlow never completes. But I thought having the take(2) would mitigate this. Any suggestions would be appreciated!

like image 456
SamCosta1 Avatar asked Aug 31 '25 17:08

SamCosta1


1 Answers

From my limited understanding I think it's something to do with the fact that SharedFlow never completes.

You're right, this is more or less the problem. Flow is based on Coroutines and the coroutine has not completed.

The best way to unit test Flows in my opinion is 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()
}

There is also an open issue about this exact "problem":

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

like image 108
shredder Avatar answered Sep 02 '25 07:09

shredder