Home > Back-end >  Detected use of different schedulers when testing with coroutines
Detected use of different schedulers when testing with coroutines

Time:11-02

I have a class that takes a coroutine dispatcher as a parameter that I am trying to test. In my tests I use @Before to setup my class before each test is run

@OptIn(ExperimentalCoroutinesApi::class)
@Before
fun setup() = runTest {
    .....
    val dispatcher = StandardTestDispatcher(testScheduler)
    scheduleService = ScheduleService(dispatcher)
}

I have a test that I am trying to run that has a SharedFlow that I want to check the value of so I also use runTest with that test

@OptIn(ExperimentalCoroutinesApi::class)
@Test
fun testFullScheduleCreation() = runTest{
    ......
    val data = scheduleService.scheduleChangedListener.first()
}

When I try to run the test I get an error

Detected use of different schedulers. If you need to use several test coroutine dispatchers, create one TestCoroutineScheduler and pass it to each of them.

The error is because of my use of @Before but I am not sure how to fix the error without copying all code in that setup method to each test

CodePudding user response:

There are a few ways to share a dispatcher between tests. The simplest is to call Dispatchers.setMain(...) in your setup. If the main dispatcher is set to a TestDispatcher, the runTest function will use it for all subsequent tests.

@Before
fun setup() {
    val dispatcher = StandardTestDispatcher()
    scheduleService = ScheduleService(dispatcher)
    Dispatchers.setMain(dispatcher)
}

If you use this approach, you should also call Dispatchers.resetMain() in a test teardown function.

If you prefer to do it manually, you can also pass the dispatcher to runTest.

lateinit var dispatcher: TestDispatcher

@Before
fun setup() {
    dispatcher = StandardTestDispatcher()
    scheduleService = ScheduleService(dispatcher)
}

@Test
fun myTest() = runTest(dispatcher) {
    ...
}

As an alternative, you can also call scope.runTest to use a shared scope that contains a dispatcher.

lateinit var scope: TestScope

@Before
fun setup() {
    val dispatcher = StandardTestDispatcher()
    scope = TestScope(dispatcher)
    scheduleService = ScheduleService(dispatcher)
}

@Test
fun myTest() = scope.runTest {
    ...
}
  • Related