Skip to content

Can not control virtual time for multiple delay calls when using runTest #164

Closed
@byencho

Description

@byencho

When using 0.12.0, it appears that the virtual time of the test cannot be controlled when using runTest after the first call to awaitItem when there are multiple delay calls. Consider the following test:

    @Test
    fun virtualTimeCanBeControlled() = runTest {
        flow {
            delay(5000)
            emit("1")
            delay(5000)
            emit("2")
        }
            .test {
                expectNoEvents()

                advanceTimeBy(5000)

                expectNoEvents()
                runCurrent()
                assertEquals("1", awaitItem())

                advanceTimeBy(5000)

                expectNoEvents() // <---------- Fails here
                runCurrent()
                assertEquals("2", awaitItem())

                awaitComplete()
            }
    }

This fails with the following error where indicated:

Expected no events but found Item(2)
app.cash.turbine.TurbineAssertionError: Expected no events but found Item(2)
	at app//app.cash.turbine.ChannelKt.unexpectedEvent(channel.kt:258)
	at app//app.cash.turbine.ChannelKt.unexpectedResult-JslgfBc(channel.kt:253)
	at app//app.cash.turbine.ChannelKt.expectNoEvents(channel.kt:71)
	at app//app.cash.turbine.ChannelTurbine.expectNoEvents(Turbine.kt:184)
	...

This test passes, however, when using runBlocking and a manually-supplied UnconfinedTestDispatcher:

    private val testDispatcher = UnconfinedTestDispatcher()

    @Test
    fun virtualTimeCanBeControlled() = runBlocking {
        flow {
            delay(5000)
            emit("1")
            delay(5000)
            emit("2")
        }
            .flowOn(testDispatcher)
            .test {
                expectNoEvents()

                testDispatcher.scheduler.advanceTimeBy(5000)

                expectNoEvents()
                testDispatcher.scheduler.runCurrent()
                assertEquals("1", awaitItem())

                testDispatcher.scheduler.advanceTimeBy(5000)

                expectNoEvents()
                testDispatcher.scheduler.runCurrent()
                assertEquals("2", awaitItem())

                awaitComplete()
            }
    }

This may be related to the changes in #151, which bases logic on whether the current scope is using a test scheduler.

  • Kotlin version : 1.7.10
  • Coroutines version : 1.6.4

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions