Kotlin Mockk тест для отмены отмены сопрограммы - PullRequest
0 голосов
/ 31 марта 2020

У меня есть классы

// 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...
    }
}

Когда я делаю

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

Работа отменяется и вызывается продолжение.invokeOnCancellation (), я проверил это с помощью операторов println. Но я хочу издеваться, если вызывается метод call.cancel или нет, используя библиотеку mockk.

Я застрял на этом, нужна помощь.

Ответы [ 2 ]

0 голосов
/ 01 апреля 2020

В вашем классе выставьте NetworkCaller, чтобы его можно было отключить для проверки во время тестирования:

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...
    }
}

Затем вы можете использовать mockk в своем тесте:

@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)
}
0 голосов
/ 31 марта 2020

вам нужно выполнить незначительный рефакторинг, чтобы уменьшить связь между Request и NetworkCaller

, затем использовать этот фиктивный объект только для отметки, если функции были вызваны

object : CancellableAction {
            override fun call() {
                callFunctionInvoked = true
            }

            override fun cancel() {
                cancelFunctionInvoked = true
            }
        }

Класс

package org.example

import kotlinx.coroutines.suspendCancellableCoroutine

interface CancellableAction {
    fun call()
    fun cancel()
}

class NetworkCaller : CancellableAction {
    override fun call() {
        // performs some real operation
    }

    override fun cancel() {
        // .... cancels the request
    }
}

class Request(val call: CancellableAction) {
    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...
    }
}

Тестовый файл

package org.example

import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import org.junit.Test

internal class NetworkCallerTest {
    @Test
    fun testRequestCancellation() {
        var callFunctionInvoked = false
        var cancelFunctionInvoked = false
        val request = Request(object : CancellableAction {
            override fun call() {
                callFunctionInvoked = true
            }

            override fun cancel() {
                cancelFunctionInvoked = true
            }
        })
        val job = GlobalScope.launch {
            val response = request.asyncRequest()
            println(response)
        }
        runBlocking {
            job.cancel()
            job.join()
        }

        assert(cancelFunctionInvoked)
    }
}
...