Have started to try to use kotlinx-coroutines-test
(https://github.com/Kotlin/kotlinx.coroutines/blob/master/core/kotlinx-coroutines-test/README.md) in JUnit unit test but getting following error when i call Dispatchers.setMain()
java.lang.IllegalArgumentException: TestMainDispatcher is not set as main dispatcher, have Main[missing, cause=java.lang.AbstractMethodError: kotlinx.coroutines.test.internal.TestMainDispatcherFactory.createDispatcher()Lkotlinx/coroutines/MainCoroutineDispatcher;] instead.
at kotlinx.coroutines.test.TestDispatchers.setMain(TestDispatchers.kt:22)
I've tried calling Dispatchers.setMain(Dispatchers.Unconfined)
and also passing in val mainThreadSurrogate = newSingleThreadContext("UI thread")
. It looks like issue isn't anyway with value being passed in but rather it's tripping up in mainDispatcher
test in following
public fun Dispatchers.setMain(dispatcher: CoroutineDispatcher) {
require(dispatcher !is TestMainDispatcher) { "Dispatchers.setMain(Dispatchers.Main) is prohibited, probably Dispatchers.resetMain() should be used instead" }
val mainDispatcher = Dispatchers.Main
require(mainDispatcher is TestMainDispatcher) { "TestMainDispatcher is not set as main dispatcher, have $mainDispatcher instead." }
mainDispatcher.setDispatcher(dispatcher)
}
This is because the Dispatchers.Main uses Android main looper which is not available during unit tests. That’s available in instrumentation tests but not in unit tests. We need to solve the problem by replacing the Dispatchers with a TestCoroutineDispatcher, which allows us to control the execution of the coroutines when we are doing tests.
Note that Dispatchers.setMain is only needed if you use viewModelScope or you hardcode Dispatchers.Main in your codebase. TestCoroutineDispatcher is a dispatcher that gives us control of how coroutines are executed, being able to pause/resume execution and control its virtual clock.
Inject Dispatcher to test Coroutine Dispatchers other than Dispatchers.Main e.g., Dispatchers.IO For the demonstration of the project, we will be using the following three dependencies: A suspending function is a function that can be paused and resumed at a later time.
So far, we have found ways to test our Dispatcher.IO and Dispatcher.Main Coroutines. By default, Coroutines work for Dispatcher.Main, but to test Dispatcher.IO, we have to use the TestCoroutineDispatcher for replacing the main dispatchers with the test dispatcher.
Try adding core as a dependency on your test. It solved the problem for me.
testImplementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.1.0")
Turned out issue was I was using older version of kotlinx-coroutines-core
dependency. When I updated to v1.1.0 it worked (thanks @vigit for helping trigger that realisation!)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With