Home > front end >  How to simulate isActive value in false in a Koltin Coroutine test?
How to simulate isActive value in false in a Koltin Coroutine test?

Time:06-07

I would like to cover the throw line after the while loop in a suspend function like this

suspend fun doWork(): Result<Any> {
    while(isActive) { 
        /* ... do something */
        return something
    }
    throw Exception("...")
}

This is a generic idea of real code and I have tried two things to reach the solution:

  1. Create a fake job but when I implemented Job interface I found some @InternalCoroutinesApi annotations so if not possible go by this way
  2. Create an internal coroutine in the test function like this
@Test(expected = Exception::class)
fun `test when job is not active`() = coroutineDispatcher.runBlockingTest {
    launch(coroutineContext) {
        cancel()

        val sut = doWork()
    }
} 

But this last one gives me a false positive and Jacoco it's not taking it. Any idea or suggestion?

CodePudding user response:

This is not really an answer, but there is a high chance you don't need isActive here at all.

You could just use while(true) and forget about the throw after the loop. If you have suspend function calls in the loop, they will likely detect cancellation on their own. If not, you can yield() to add some suspension points.

Note that isActive only works correctly if the current coroutine context has a Job, which might not always be the case (suspend fun main doesn't have a job, nor does GlobalScope). This is one of the reasons why I suggested deprecating CoroutineContext.isActive and this issue was opened.

CodePudding user response:

I got the solution. Point two in a way to create an inner coroutine and cancel it was ok to get isActive with a false value

@Test(expected = Exception::class)
fun `test when job is not active`() = coroutineDispatcher.runBlockingTest {
    launch(coroutineContext) {
        cancel()

        val sut = doWork()
    }
} 

The real clue for getting the solution and right coverage was to set JaCoCo version to the last one in Gradle

jacoco {
    toolVersion = "0.8.8"
}

That's all. Thank you to everybody for trying to help me.

  • Related