Unit tests with coroutines¶
The CoroutineTest
base class provides some often useful helpers for working with coroutines.
class MyTest : CoroutineTest() {
// This works because MainScope/Dispatchers.Main is automatically set up correctly by CoroutineTest
val viewModel = MyViewModel()
// Let's use a mock to test the events emitted by MyViewModel
val events: MyEvents = mock()
@Before
fun setup() {
// You can access the TestCoroutineScope directly to launch some background processing.
// In this case, let's process MyViewModel's events.
testCoroutineScope.launch {
viewModel.eventNotifier.collect { events.it() }
}
}
@Test
fun someTest() = runBlockingTest {
viewModel.doSomething()
advanceUntilIdle()
verify(events).someEvent()
}
}
This also sets up a global dispatchers
variable which you can use in all of your code instead of passing a CoroutineDispatcher
around as arguments:
// Use this instead of Dispatchers.IO. In unit tests this will automatically use
// the TestCoroutineDispatcher instead. Outside of unit tests it points to Dispatchers.IO.
// You can also define your own overrides if you want.
withContext(dispatchers.io) {
// do some IO
}
If you can’t derive from CoroutineTest
directly (e.g. because you have some other base test class), you can alternatively use composition with the CoroutineTestRule
:
class MyTest {
val rule = CoroutineTestRule()
@Test
fun someTest() = rule.runBlockingTest {
// ...
}
}