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?
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 async
Deferred
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.
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()
}
}