Skip to content

Using TestCoroutineDispatcher

Devrath edited this page Jul 3, 2021 · 16 revisions

What is TestCoroutineDispatcher

  • This is a type of co-routine dispatcher that is used to test the coroutines.
class TestCoroutineDispatcher : CoroutineDispatcher, Delay, DelayController
  • As seen above the testCoroutineDispatcher extends the classes coroutineDispatcher, delay, delayController.
  • It performs immediate and lazy execution of co-routines.
  • By default testCoroutineDispatcher is immediate meaning any tasks that are scheduled to run immediately is executed immediately
  • If there is a delay the virtual clock is advanced by the amount of delay involved.

How to Unit Test a suspend function

  • Coroutines provides an easy way and elegant way of executing the asynchronous code. But sometimes coroutines are hard to unit test.
  • Most important thing to remember here is, to understand how to build a coroutine in unit test and when executing that coroutine in the unit test, we need to understand how to wait for all the jobs in the unit test to complete before completing the test function.
  • Next in the task is we want to run our tests as fast as possible without waiting for the delay in coroutines to finish.
Steps in performing the unit testing
Set up the gradle
Defining the coroutineTestRule
Applying the coroutineTestRule
[Define a sample heavy operation()
Possible options to take for unit testing

Gradle

ext {
    coroutines = "1.3.1"
}

dependencies {
    implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines"
    implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines"

    // testImplementation for pure JVM unit tests
    testImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:$coroutines"

    // androidTestImplementation for Android instrumentation tests
    androidTestImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:$coroutines"
}

Defining the coroutineTestRule

  • This class extends TextWatcher
  • Define it in the util package in the test folder
@ExperimentalCoroutinesApi
class CoroutineTestRule(val testDispatcher: TestCoroutineDispatcher = TestCoroutineDispatcher()) : TestWatcher() {
    override fun starting(description: Description?) {
        super.starting(description)
        Dispatchers.setMain(testDispatcher)
    }

    override fun finished(description: Description?) {
        super.finished(description)
        Dispatchers.resetMain()
        testDispatcher.cleanupTestCoroutines()
    }
}
  • Above rule takes care of watching the tests starting and the finishing.
  • There is a reference to testDispatcher.
  • As the tests start and finish, this replaces Dispatchers.Main with our testDispatcher.

Applying the coroutineTestRule

@ExperimentalCoroutinesApi
class HeavyWorkerTest {
    
    @get:Rule
    var coroutinesTestRule = CoroutineTestRule()

    // Some tests written
}

Clone this wiki locally