Turbine para TESTING de FLOW en Android

turbine testing flow android

Turbine para Testing de Flow en Android

Turbine es una biblioteca que nos ayuda a hacer más sencillo el testing de Flow en Android.

Cuando lo que tenemos que comprobar es muy sencillo, quizá no haga falta darle muchas más vueltas. Pero cuando la cosa se empieza a complicar con la combinación de distintos flows, esta excelente biblioteca de testing, nos resuelve muy bien la papeleta.

En audio premium está abajo del vídeo. Como curiosidad, comentarte que luego de grabarlo, he caído en que la pronunciación no es como la hago ahí, jajaja. Fonéticamente sería: ˈtərˌbīn.

Entre esta y la bio de Alan Turing, vaya tela… 😅

Este contenido está restringido.
Adquiere alguna formación.
O suscríbete para difrutar de los audios y vídeos exclusivos de Los androides Premium.

Antes de empezar, tienes el todo el código de ejemplo, en este repositorio en Github.

Y por cierto, también hago uso de MockK y Kluent, para tener los tests más legibles.

Flow

Si por alguna de aquellas, esto de los flows no tienes claro lo que es, te recomiendo que antes de nada, le pegues una oída al episodio 17 del podcast en el que te hablé del uso con LiveData. Algunas de las cosas que hay comenté están en desuso, pero es un buen punto por el que comenzar.

Para simplificar, son parte de las corrutinas. Imagínatelo como un flujo de datos en background. Tienes un punto de tu app que se va actualizando de manera reactiva. Pero en lugar de que haya un único valor cambiante, lo que que hay es un flujo de valores.

Aclarado esto, vamos ya con lo que nos acontece hoy.

Turbine al rescate

El nombre de la biblioteca, hace alusión a lo que vendría a ser una turbina. Turbina, flujos, cañerías… todo muy relacionado con el maravilloso mundo de esta parte de las corrutinas que es Flow. 😉

Imaginemos que tenemos un ViewModel tal que así:

@HiltViewModel
class MainViewModel @Inject constructor(
    private val getRandomBooleanUseCase: GetRandomBooleanUseCase,
    @IO private val dispatcher: CoroutineDispatcher,
) : ViewModel() {

    private val _uiState = MutableStateFlow<UiState>(UiState.Idle)
    val uiState get() = _uiState.asStateFlow()

    fun changeUiState() {
        viewModelScope.launch(dispatcher) {
            if (getRandomBooleanUseCase()) {
                _uiState.emit(UiState.Success)
            } else {
                _uiState.emit(UiState.Error)
            }
        }
    }

    sealed class UiState {
        object Idle : UiState()
        object Error : UiState()
        object Success : UiState()
    }
}

Si quisieramos testear lo que sucede al cambiar el estado de la UI, podríamos hacer lo siguiente:

@Test
fun `GIVEN success WHEN changeUiState THEN uiState should be Success`() =
    runTest(dispatcher) {
        every { getRandomBooleanUseCase() } returns true

        viewModel.changeUiState()

        viewModel.uiState.value shouldBeInstanceOf MainViewModel.UiState.Success::class
    }

Y para hacer este mismo test usando Turbine, quedaría así:

@Test
fun `GIVEN success WHEN changeUiState THEN uiState should be Success using Turbine`() =
    runTest(dispatcher) {
        every { getRandomBooleanUseCase() } returns true

        viewModel.changeUiState()

        viewModel.uiState.test {
            val item = awaitItem()
            item shouldBeInstanceOf MainViewModel.UiState.Success::class
        }
    }

Este caso en particular es bastante simple. Y quizá no hiciera demasiada falta el empleo de Turbine. Pero si empezamos a añadir más complejidad, sí se vuelve muy útil.

Que dicho sea de paso, tanto los parameterized tests como las distintas bibliotecas de testing con Kotlin, nos podrían venir también de perlas.

Por eso, ahora es tu turno:

¿Qué ejemplo se te ocurre para el que esta biblioteca pueda ser de más utilidad?

👉️ Coméntalo en la comunidad. 👈️

Publicado: 2023-05-29 Actualizado: 2024-01-07