Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Coroutine testing fails with "This job has not completed yet"

I'm following Craig Russell's blog post about testing coroutines: https://craigrussell.io/2019/11/unit-testing-coroutine-suspend-functions-using-testcoroutinedispatcher/ but I can't get this test to pass:

@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)
}

Basically I'm launching a bunch of parallel jobs and want to get the result once all of them are finished. I'm getting this, by now classical exception:

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

Please advise how to get this to work as intended.

My complete code:

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()
    }
}
like image 648
Robert Avatar asked Jul 12 '20 07:07

Robert


Video Answer


2 Answers

Solved.

I totally blame Android Studio's auto-completion for this. :)

I simply ran the wrong "runBlockingTest()".

Replace this line:

fun multipleLaunch() = runBlockingTest {

with this line:

fun multipleLaunch() = coroutinesTestRule.testDispatcher.runBlockingTest {
like image 82
Robert Avatar answered Oct 19 '22 17:10

Robert


Instead of runBlockingTest{} I used runBlocking{} because of Issue 1204

like image 32
Tonnie Avatar answered Oct 19 '22 18:10

Tonnie