协程测试失败,提示"This job has not completed yet"。

6

我正在遵循Craig Russell的博客文章,该文章介绍了有关测试协程的内容:https://craigrussell.io/2019/11/unit-testing-coroutine-suspend-functions-using-testcoroutinedispatcher/但是我无法通过此测试:

@Test
fun multipleLaunch() = runBlockingTest {
    var result = 0
    val jobs = mutableListOf<Job>()
    for (j in 0 until 10) {
        val job = launch(testDispatcherProvider.io()) {
            delay(1000)
            result++
        }
        jobs.add(job)
    }
    jobs.forEach { job ->
        job.join()
    }
    assertEquals(10, result)
}

基本上我要启动一堆并行作业,希望在它们全部完成后得到结果。 到目前为止,我已经遇到了一个经典的例外:

java.lang.IllegalStateException: This job has not completed yet

请指导如何按预期工作。
我的完整代码:
class LaunchTest {
    @get:Rule
    var coroutinesTestRule = CoroutineTestRule()

    val testDispatcherProvider = object : DispatcherProvider {
        override fun io(): CoroutineDispatcher = coroutinesTestRule.testDispatcher
    }

    @Test
    fun multipleLaunch() = runBlockingTest {
        var result = 0
        val jobs = mutableListOf<Job>()
        for (j in 0 until 10) {
            val job = launch(testDispatcherProvider.io()) {
                delay(1000)
                result++
            }
            jobs.add(job)
        }
        jobs.forEach { job ->
            job.join()
        }
        assertEquals(10, result)
    }
}

class CoroutineTestRule constructor(val testDispatcher: TestCoroutineDispatcher = TestCoroutineDispatcher()) : TestWatcher() {
    override fun starting(description: Description?) {
        super.starting(description)
        Dispatchers.setMain(testDispatcher)
    }

    override fun finished(description: Description?) {
        super.finished(description)
        Dispatchers.resetMain()
        testDispatcher.cleanupTestCoroutines()
    }
}

这是一个相当古老的问题,有些人建议使用runBlocking而不是runBlockingTest - Animesh Sahu
1
谢谢。我看到了那个问题。但是我怀疑我的代码中还有其他错误,因为我确实注入了一个测试调度程序而不是Dispatchers.IO。 - Robert
2个回答

5
解决了。
这完全是 Android Studio 的自动补全的问题。 :)
我只是运行了错误的 "runBlockingTest()"。
替换此行:
fun multipleLaunch() = runBlockingTest {

使用这行代码:

fun multipleLaunch() = coroutinesTestRule.testDispatcher.runBlockingTest {

4

由于 Issue 1204,我使用了 runBlocking{} 而不是 runBlockingTest{}


2
这样做会失去一些在此处提到的runBlockingTest的功能 https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-test/。 - Hassan Alizadeh

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接