DEV Community

myougaTheAxo
myougaTheAxo

Posted on • Originally published at zenn.dev

Coroutine Testing in Kotlin - runTest, Turbine, and TestDispatchers (v2)

Testing coroutines requires special handling to manage time and control execution flow. Learn how to use runTest, Turbine, and TestDispatcher for robust async tests.

Basic Coroutine Testing with runTest

The runTest builder automatically advances virtual time and manages dispatcher scope:

@Test
fun testFlowEmission() = runTest {
    val flow = flowOf(1, 2, 3)
    val results = mutableListOf<Int>()

    flow.collect { results.add(it) }

    assertEquals(listOf(1, 2, 3), results)
}
Enter fullscreen mode Exit fullscreen mode

Testing Delayed Emissions with advanceTimeBy

Control virtual time progression to test delays:

@Test
fun testDelayedEmission() = runTest {
    val flow = flow {
        emit(1)
        delay(1000)
        emit(2)
    }

    val results = mutableListOf<Int>()
    launch {
        flow.collect { results.add(it) }
    }

    advanceTimeBy(500)
    assertEquals(listOf(1), results)

    advanceUntilIdle()
    assertEquals(listOf(1, 2), results)
}
Enter fullscreen mode Exit fullscreen mode

Advanced Testing with Turbine

Turbine simplifies Flow testing with expressive assertions:

@Test
fun testFlowWithTurbine() = runTest {
    val viewModel = MyViewModel()

    viewModel.uiState.test {
        awaitItem().apply {
            assertEquals("Loading", status)
        }
        advanceUntilIdle()
        awaitItem().apply {
            assertEquals("Success", status)
        }
        expectNoEvents()
    }
}
Enter fullscreen mode Exit fullscreen mode

Custom TestDispatcher Setup

Create scoped test dispatchers for complex scenarios:

val testDispatcher = StandardTestDispatcher()
val testScope = TestScope(testDispatcher)

@Test
fun testWithCustomDispatcher() {
    testScope.runTest {
        val job = launch {
            delay(100)
            println("Done")
        }
        advanceUntilIdle()
        job.join()
    }
}
Enter fullscreen mode Exit fullscreen mode

Proper coroutine testing ensures reliable asynchronous code. Combine these tools to handle all timing scenarios effectively.

8 Android app templates on Gumroad

Top comments (0)