web-dev-qa-db-fra.com

Lorsque j'utilise des coroutines kotlin, comment puis-je tester unitaire une fonction qui appelle une fonction de suspension?

J'ai une classe comme ça

class SomeClass {
    fun someFun() {
        // ... Some synchronous code
        async {
            suspendfun() 
        }
    }

    private suspend fun suspendFun() {
         dependency.otherFun().await()
         // ... other code
    }
}

Je veux faire un test unitaire someFun() j'ai donc écrit un test unitaire qui ressemble à ceci:

@Test
fun testSomeFun() {
    runBlocking {
        someClass.someFun()
    }

    // ... verifies & asserts
}

Mais cela ne semble pas fonctionner car runBlocking ne bloque pas réellement l'exécution jusqu'à ce que tout ce qui se trouve dans runBlocking soit terminé. Si je teste suspendFun() directement dans runBlocking cela fonctionne comme prévu mais je veux pouvoir tester someFun() tous ensemble.

Une idée de comment tester une fonction avec du code de synchronisation et asynchrone?

21
user1809913

Correction de l'async

Telle qu'implémentée, votre someFun() ne fera que "tirer et oublier" le résultat async. Par conséquent, runBlocking ne fait aucune différence dans ce test.

Si possible, faites que someFun() retourne asyncDeferred puis, dans runBlocking, appelez await dessus.

fun someFun(): Deferred<Unit> {
    // ... Some synchronous code
    return async {
        suspendFun()
    }
}

Puis le test:

runBlocking {
    SomeClass().someFun().await()
}

Cette question/réponse est une bonne ressource pour plus d'informations.

alternative: utiliser le lancement

Il est également possible d'éviter async au profit de l'utilisation des fonctions suspend et d'une coroutine créée par launch:

suspend fun someFun() {
    // ... Some synchronous code
    suspendFun()
}

private suspend fun suspendFun() {
    delay(1000)
    println("executed")
    // ... other code
}

Le test utilise launch et le runBlocking extérieur attend implicitement sa fin:

val myScope = GlobalScope
runBlocking {
    myScope.launch {
        SomeClass().someFun()
    }
}
13
s1m0nw1