kotlinx.coroutines icon indicating copy to clipboard operation
kotlinx.coroutines copied to clipboard

Version 1.10.x Dispatchers issue

Open mkowol-n opened this issue 7 months ago • 1 comments
trafficstars

After bumping the library version to 1.10.1 and running my unit tests i'm getting an error: Dispatchers.Main was accessed when the platform dispatcher was absent and the test dispatcher was unset. Please make sure that Dispatchers.setMain() is called before accessing Dispatchers.Main and that Dispatchers.Main is not accessed after Dispatchers.resetMain(). java.lang.IllegalStateException: Dispatchers.Main was accessed when the platform dispatcher was absent and the test dispatcher was unset. Please make sure that Dispatchers.setMain() is called before accessing Dispatchers.Main and that Dispatchers.Main is not accessed after Dispatchers.resetMain().

Once i downgrade the version to 1.9.0 everything works just fine.

Setting Dispatcher in @Before annotation does not change anything.

mkowol-n avatar Mar 26 '25 12:03 mkowol-n

Can't reproduce: setMain works without issues for me. Could you provide a project where you encounter this issue?

dkhalanskyjb avatar Mar 26 '25 12:03 dkhalanskyjb

I've also noticed this issue when constructing TestLifecycleOwner in a unit test if it's a class level property of the test. The default parameter for the dispatcher is Dispatchers.Main.immediate. For example this will fail

class ExampleTest {

    val dispatcher = Dispatchers.Main.immediate

    @Test
    fun test() {}

}

nd-jchu avatar Jul 03 '25 06:07 nd-jchu

@nd-jchu, these instructions may be of help: https://developer.android.com/kotlin/coroutines/test#setting-main-dispatcher

dkhalanskyjb avatar Jul 03 '25 06:07 dkhalanskyjb

Thanks! In the case where we access Dispatchers.Main during class init, only setting Dispatchers.setMain from starting doesn't fix it unless we also call setMain from init in the custom rule. Doing this fixes it.

class MainDispatcherRule(
    val testDispatcher: TestDispatcher = UnconfinedTestDispatcher(),
) : TestWatcher() {

    init {
        Dispatchers.setMain(testDispatcher)
    }

    override fun starting(description: Description) {
        Dispatchers.setMain(testDispatcher)
    }

    override fun finished(description: Description) {
        Dispatchers.resetMain()
    }
}

We may need to provide additional guidance for those upgrading as I could imagine existing tests failing for similar reasons. Especially if there are dependencies that access Dispatchers.Main upon init such as TestLifecycleOwner.

https://developer.android.com/reference/kotlin/androidx/lifecycle/testing/TestLifecycleOwner#TestLifecycleOwner(androidx.lifecycle.Lifecycle.State,kotlinx.coroutines.CoroutineDispatcher)

nd-jchu avatar Jul 03 '25 15:07 nd-jchu

We may need to provide additional guidance for those upgrading

Sorry, but what upgrades do you mean? kotlinx.coroutines.test has had this behavior almost since the beginning.

dkhalanskyjb avatar Jul 03 '25 17:07 dkhalanskyjb