Prueba unitaria con canal en Kotlin
Empecé a aprender cómo usar el Canal pero tengo problemas con las pruebas unitarias. Por ejemplo con la clase:
class TestOp (private val channel: Channel<string>) {
suspend fun op() {
channel.send("new")
}
}
y para probarlo:
@ExtendWith(CoroutineExecutorExtension::class)
@RunWith(JUnitPlatform::class)
internal class TestOpTest{
@Test
fun testOpReturnNew() {
runBlockingTest {
val channel = Channel<string>()
val test = TestOp(channel = channel)
test.op()
assertEquals("new", channel.receive())
}
}
}
donde:
@ExperimentalCoroutinesApi
class CoroutineExecutorExtension : InstantExecutorExtension() {
private val testCoroutineDispatcher = TestCoroutineDispatcher()
override fun beforeEach(context: ExtensionContext?) {
super.beforeEach(context)
Dispatchers.setMain(testCoroutineDispatcher)
}
override fun afterEach(context: ExtensionContext?) {
super.afterEach(context)
Dispatchers.resetMain()
testCoroutineDispatcher.cleanupTestCoroutines()
}
}
@ExperimentalCoroutinesApi
open class InstantExecutorExtension : BeforeEachCallback, AfterEachCallback {
override fun beforeEach(context: ExtensionContext?) {
ArchTaskExecutor.getInstance()
.setDelegate(object : TaskExecutor() {
override fun executeOnDiskIO(runnable: Runnable) = runnable.run()
override fun postToMainThread(runnable: Runnable) = runnable.run()
override fun isMainThread(): Boolean = true
})
}
override fun afterEach(context: ExtensionContext?) {
ArchTaskExecutor.getInstance().setDelegate(null)
}
}
Obtengo el error:
This job has not completed yet
java.lang.IllegalStateException: This job has not completed yet
at kotlinx.coroutines.JobSupport.getCompletionExceptionOrNull(JobSupport.kt:1190)
at kotlinx.coroutines.test.TestBuildersKt.runBlockingTest(TestBuilders.kt:53)
at kotlinx.coroutines.test.TestBuildersKt.runBlockingTest$default(TestBuilders.kt:45)
Si uso runBlocking
, la prueba nunca se completa.
¿Cuál es la forma correcta de probarlo?
davy.ai
El problema con la prueba dada es que el canal no se está cerrando correctamente, lo que provoca que la prueba se quede colgada indefinidamente. Para solucionar esto, debemos asegurarnos de que el canal se cierre después de que la prueba haya terminado. Para hacer esto, podemos modificar el código de la prueba de la siguiente manera:
Al agregar
channel.close()
al final de la prueba, nos aseguramos de que el canal se cierre correctamente después de que la prueba haya terminado. Esto debería solucionar el problema de la prueba que se queda colgada indefinidamente.Otra cosa a tener en cuenta es que podemos usar la función
runBlockingTest
directamente en nuestra función de prueba, sin tener que definirla por separado en una extensión. Esto simplifica nuestro código y lo hace más legible.Esta debería ser la forma correcta de probar la clase
TestOp
utilizando canales y corutinas.