Cómo mockear clases finales en Kotlin con Mockito 2 (KDA 23)
Antonio Leiva

Una de las pegas que más se le suele poner a Kotlin, como ya hablábamos en un artículo anterior, es que todas las clases y funciones son por defecto cerradas.

Esto quiere decir que si quieres mockear cualquier clase (algo que puede ser bastante habitual en el testing en Java), necesitas o bien hacerla abierta, con la palabra reservada open, o bien crearte una interfaz por encima.

Ambas opciones pueden ser tediosas, y la verdad es que suponen una limitación cuando la gente viene de programar en Java.

Por suerte, Mockito 2 ha eliminado esta restricción, y hoy te voy a enseñar cómo hacerlo.

Si quieres aprender cuál es la situación de Kotlin en el mercado, por qué debes aprenderlo y los primeros pasos para que veas lo fácil que es, he preparado un training gratuito de hora y media al que puedes unirte haciendo click aquí.

¿Cuál es la problemática?

Imagina que tienes una clase en Kotlin con esta forma:

class ClosedClass {

    fun doSomething() {
    }
}

Y que quieres testear que se llama a su método doSomething.

La forma que tendría el test sería la siguiente:

@Test fun testClosedClass() {
    val c = Mockito.mock(ClosedClass::class.java)
    c.doSomething()
    verify(c).doSomething()
}

Si ejecutas esto con una versión de Mockito 1.x, obtendrás el siguiente error:

Mockito cannot mock/spy following:
– final classes
– anonymous classes
– primitive types

Actualiza las dependencias a Mockito 2

Como hemos dicho, Mockito 2 es capaz de mockearlo todo, así que vamos a actualizar la dependencia. En el momento de escribir este artículo la última versión es la 2.2.6. Pero verifícalo porque están actualizando muy a menudo últimamente.

testCompile 'org.mockito:mockito-core:2.2.6'

Así que ahora volvemos a ejecutar nuestro código, pero… ¡otra vez falla!

Mockito cannot mock/spy because :
– final class

Ya no nos limita mockear clases anónimas o tipos primitivos, pero sí clases finales ¿A qué se debe esto?

Esta opción aún es un poco experimental, y requiere que la activemos a mano.

Activa la opción de mockear clases finales

Para ello, tendrás que crear un archivo en la carpeta test/resources/mockito-extensions llamado org.mockito.plugins.MockMaker :

mockito-2-activacion-clases-finales

Es un simple archivo de texto, en el que hay que escribir:

mock-maker-inline

Nada más.

Ahora ya puedes ejecutar de nuevo el test, y verás que se ejecuta sin problemas. ¡Genial!

Mockear propiedades

También puedes mockear propiedades sin problema. Si cambiamos el código de la clase a este, por ejemplo:

class ClosedClass(val prop: Int) {

    fun doSomething() {
    }
}

Ahora vamos a mockear el valor de la property:

@Test fun testClosedClass() {
    val c = Mockito.mock(ClosedClass::class.java)
    `when`(c.prop).thenReturn(3)

    val prop = c.prop
    assertEquals(3, prop)
}

Cómo ves, le estoy pidiendo que devuelva 3 cuando se le llame, y posteriormente, compruebo que el valor es el correcto.

También puedes comprobar que una propiedad se ha llamado con:

verify(c).prop

Conclusión

Como ves, todas las limitaciones han desaparecido gracias a la nueva actualización de la librería de mocks más conocida para Java.

Ya no hay excusa para que no escribas todos tus tests en Kotlin.

Si te gusta lo que has visto, te animo a que te apuntes al training gratuito, donde te contaré todo lo que necesitas para aprender a crear tus Apps Android en Kotlin desde cero.

Quizá también te interese…

2 formas de recolectar Flows en la UI que SÍ funcionan

2 formas de recolectar Flows en la UI que SÍ funcionan

En la serie de artículos sobre Programación Reactiva con Flow hemos visto muchos conceptos, y hemos aprendido cómo aplicarlos al desarrollo Android. Pero hay algo que no hemos hecho del todo bien. Esto es la recolección de Flows desde la Activity (o el Fragment, en...

Cómo hacer tests de Corrutinas y Flows – Paso a Paso

Cómo hacer tests de Corrutinas y Flows – Paso a Paso

¡Vaya viaje por el que hemos pasado en estos artículos! Hace ya varios de ellos empezamos hablando sobre la programación reactiva con Flow, y hemos aprendido un montón de conceptos e ideas sobre cómo aplicarlos en el día a día. Pero nada de esto está completo si no...

Convertir cualquier callback en un Flow con CallbackFlow

Convertir cualquier callback en un Flow con CallbackFlow

Existen varios tipos de Flows muy particulares que nos van a solucionar la vida cuando tengamos que hacer cosas muy concretas. Ya vimos StateFlow en un artículo anterior, y en esta ocasión hablamos de CallbackFlow ¿Qué es CallbackFlow? Es un tipo de Flow que nos...