Minion
Minion

Reputation: 1064

Kotlin Mockk test for suspend cancellable coroutine cancellation

I have classes

// final class from some library like okhttp
class NetworkCaller {
    fun call() {
        // performs some real operation
    }
    fun cancel() {
        // .... cancels the request
    }
}

class Request {
    suspend fun asyncRequest(): String = suspendCancellableCoroutine { continuation ->
        val call = NetworkCaller()
        continuation.invokeOnCancellation {
            call.cancel() // i need to write a test to mock if call.cancel is getting called or not
        }
        // rest of the code...
    }
}

When i am doing

@Test
fun testRequestCancellation() {
    val request = Request()
    val job = GlobalScope.launch {
        val response = request.asyncRequest()
        println(response)
    }
    runBlocking {
        job.cancel()
        job.join()
    }
}

The job is getting cancelled and continuation.invokeOnCancellation() is getting called, i checked with println statements. But i want to mock if the call.cancel method is getting called or not, using mockk library.

I am stuck on this, need help.

Upvotes: 4

Views: 3663

Answers (1)

DJ_Polly
DJ_Polly

Reputation: 434

In your class, expose the NetworkCaller so it can be switched out for a mock during testing:

class Request(val call: NetworkCaller = NetworkCaller()) {
    suspend fun asyncRequest(): String = suspendCancellableCoroutine { continuation ->
        continuation.invokeOnCancellation {
            call.cancel() // i need to write a test to mock if call.cancel is getting called or not
        }
        // rest of the code...
    }
}

Then you can use mockk in your test:

@Test
fun testRequestCancellation() {
    val mockkCall = mockk<NetworkCaller> {
        coEvery { cancel() } just Runs
    }

    val request = Request(mockkCall)
    val job = GlobalScope.launch {
        val response = request.asyncRequest()
        println(response)
    }
    runBlocking {
        job.cancel()
        job.join()
    }
    coVerify { mockkCall.cancel() }
    confirmVerified(mockkCall)
}

Upvotes: 1

Related Questions