使用协程进行测试时检测到使用不同的调度程序

tyc*_*czj 3 unit-testing kotlin kotlin-coroutines kotlin-flow

我有一个类,它采用协程调度程序作为我正在尝试测试的参数。在我的测试中,我通常@Before在每次测试运行之前设置我的类

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

我有一个正在尝试运行的测试,其中有一个SharedFlow我想检查其值,因此我也将其runTest与该测试一起使用

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

当我尝试运行测试时出现错误

检测到使用不同的调度程序。如果需要使用多个测试协程调度程序,请创建一个 TestCoroutineScheduler 并将其传递给每个测试协程调度程序。

该错误是由于我使用的,@Before但我不确定如何在不将该设置方法中的所有代码复制到每个测试的情况下修复该错误

Sam*_*Sam 6

有几种方法可以在测试之间共享调度程序。最简单的是调用Dispatchers.setMain(...)您的设置。如果主调度程序设置为 a TestDispatcher,该runTest函数将使用它进行所有后续测试。

@Before
fun setup() {
    val dispatcher = StandardTestDispatcher()
    scheduleService = ScheduleService(dispatcher)
    Dispatchers.setMain(dispatcher)
}
Run Code Online (Sandbox Code Playgroud)

如果您使用这种方法,您还应该调用Dispatchers.resetMain()测试拆卸函数。

如果您更喜欢手动执行此操作,也可以将调度程序传递给runTest

lateinit var dispatcher: TestDispatcher

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

@Test
fun myTest() = runTest(dispatcher) {
    ...
}
Run Code Online (Sandbox Code Playgroud)

作为替代方案,您还可以调用scope.runTest以使用包含调度程序的共享范围。

lateinit var scope: TestScope

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

@Test
fun myTest() = scope.runTest {
    ...
}
Run Code Online (Sandbox Code Playgroud)