Turbine para Kotlin: guía completa para testing de Flow
1. ¿Qué es y para qué sirve?
La librería Turbine es una herramienta moderna para probar flujos de datos asíncronos (Flow) en Kotlin. Desarrollada por Cash App, Turbine resuelve uno de los problemas más comunes al escribir tests unitarios para código asíncrono: la dificultad de verificar la emisión de valores, el manejo de errores y la finalización del flujo. A diferencia de enfoques estándar como kotlinx-coroutines-test con recolección manual, Turbine ofrece una API declarativa e intuitiva que hace que los tests sean legibles y confiables.
¿Para qué sirve Turbine? Imagina que escribes una ViewModel que se suscribe a un repositorio y transforma datos en estados de UI. Sin Turbine, tendrías que crear colectores manualmente, gestionar Jobs y sincronizar corrutinas. Turbine automatiza todo: crea una corrutina virtual, recolecta todas las emisiones en una "turbina" (de ahí su nombre) y te permite verificar cada valor en orden, ignorando estados intermedios irrelevantes. Esto es especialmente útil al probar flujos tipo BehaviourSubject, donde solo importa el estado final.
Las principales características incluyen: verificación de valores emitidos en orden estricto, omisión de valores intermedios con skip(), prueba de errores con awaitError(), verificación de finalización con awaitComplete(), y soporte para canales (Channel) y StateFlow. Turbine se integra con cualquier framework de testing (JUnit, Kotest, Spek) y no requiere configuración adicional: solo agrega la dependencia y usa testScope.
2. Instalación
Para usar Turbine en tu proyecto, agrega la siguiente dependencia en tu archivo build.gradle.kts (o build.gradle):
// build.gradle.kts
dependencies {
// Para proyectos JVM
testImplementation("app.cash.turbine:turbine:1.1.0")
// Si usas kotlinx-coroutines-test (recomendado)
testImplementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:1.9.0")
}
// Para proyectos Android (dentro del bloque android)
android {
testOptions {
unitTests.isReturnDefaultValues = true
}
}
Si usas Maven:
<dependency>
<groupId>app.cash.turbine</groupId>
<artifactId>turbine</artifactId>
<version>1.1.0</version>
<scope>test</scope>
</dependency>
Requisitos mínimos: Kotlin 1.9+, kotlinx-coroutines 1.8+. La librería es compatible con JVM, Android, JS y Native (a través de Kotlin Multiplatform).
3. Inicio rápido
Veamos un ejemplo sencillo: probar un Flow que emite tres números.
import app.cash.turbine.test
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.test.runTest
import org.junit.Test
class SimpleTurbineTest {
@Test
fun `test flow emite tres valores`() = runTest {
val flow = flowOf(1, 2, 3)
flow.test {
// awaitItem() espera la siguiente emisión y la devuelve
assertEquals(1, awaitItem())
assertEquals(2, awaitItem())
assertEquals(3, awaitItem())
// awaitComplete() verifica que el flujo terminó sin errores
awaitComplete()
}
}
}
Ejecuta este test y verás que pasa correctamente. Nota: test es una función suspend que inicia la recolección del flujo en una corrutina separada. Cada llamada a awaitItem() bloquea la corrutina actual hasta que aparezca el siguiente elemento. Si el flujo termina antes de lo esperado, el test falla con un mensaje de error claro.
4. Métodos y funciones principales
También en la biblioteca
Validación de datos en Rust: revisión de bibliotecas y frameworks
Bibliotecas WebSocket para Node.js: ws, Socket.IO, uWS — revisión completa
Trabajo con CSV en PHP: biblioteca SplFileObject y funciones integradas
Ktor para Kotlin: guía completa con ejemplos