Quizas ver primero: [[[N] Unit Testing con JUnit]]
# Mockito en Java
‘Mock’ se refiere a una tecnica utilizada para crear “mock objects”, los cuales son implementaciones de las dependencias que tiene una unidad que va a pasar por un Unit Test. Simula las dependencias y permite que se ejecute correctamente un proceso dependiente de una libreria, base de datos o de cualquier recurso externo.
Mockito es un framework de Java que implementa esta practica de crear mock objects. Es muy util y se puede usar en conjunto con JUnit para realizar muy buenos Unit Tests.
Para agregarlo debemos escribir su dependencia en nuestro gestor de dependencias (Gradle o Maven).
| |
# Usos y Problemas que Resuelven al hacer Unit Tests
Suponiendo que tuvieramos una clase como FxConverter, que convierte de una moneda a otra mediante su metodo .convert() y quisieramos probar su unidad quizas encontrariamos algunos problemas de dependencia, porque probablemente dentro de FxConverter tiene dependencias a otras clases como ‘RemoteFxRateService’, la cual a su vez podria tener sus propias dependencias, con lo cual enfrentariamos estos dos principales problemas.
- Bola de Nieve. Enfrentariamos una bola de nieve gigante con la cantidad de dependencias que podria tener una clase con otra hasta que pudiesemos llegar a probar nuestra unidad.
- Pruebas previas. Tomando en cuenta que quizas ya probamos las dependencias posteriores a nuestro FxConverter no tendria sentido instanciar todo y formar una bola de nieve, siendo que nosotros solo queremos hacer un test de la unidad FxConverter.
Para resolver estos problemas esque se crean los mock objects
# Crear Mock Objects usando Mockito
Hay dos formas principales para crear Mock Objects:
- Usando el metodo mock(Object.class)
- Usando anotaciones
Suponiendo que queremos escribir un test para nuestro FxConverter sin preocuparnos por su dependencia en RemoteFxRateService podriamos hacerlo de estas dos formas:
| |
O si preferimos utilizar anotaciones podemos hacerlo como:
| |
En este caso tenemos dos nuevas anotaciones. @ExtendWith y @Mock. (Imagino que ExtendWith declara una clase la cual hara el Mock de objetos y @Mock marca los objetos a seguir este proceso)
# Definir comportamiento
Una vez que tenemos los mock objects creados, debemos definir su comportamiento cuando sus ciertos metodos sean llamados. Para definir esto podemos utilizar dos metodos estaticos: when() y thenReturn().
Siguiendo con nuestro ejemplo, probaremos la transformacion entre dos monedas iguales y dos diferentes:
| |
Those two tests will pass, if we use another currency thats not defined inside the when() and thenReturn() methods we will fail because the behavior is not defined. If a method behavior is not defined Mockito returns a default value:
- null for objects
- 0 for integers
- false for boolean
- Empty Collections for Collections
# Argument Matchers
Adicionalmente, podemos especificar Argument Matchers para que Mockito se encargue de la busqueda y ejecucion de estos argumentos particulares, de modo que no tengamos que especificarlo todo nosotros mismos.
Debemos tener en cuenta que, si utilizamos un Argument Matcher todos los argumentos de nuestros metodos deben ser Matchers.
| |
Para ver todos los matchers disponibles podemos leer la Documentacion oficial de Mockito. Sin embargo, entre los mas usados tenemos a: any(), anyString(), anyInt(), eq(value).
# Throwing Exceptions
Finalmente, Mockito tambien permite definir el comportamiento de un metodo cuando tiene errores. Para esto en ves de thenReturn() utilizamos el metodo thenThrow().
Finalmente, nuestra clase quedaria de esta forma, teniendo en cuenta que cuando IllegalStateException es tirada, tenemos un try-catch en RemoteFxRateService que devuelve un BigDecimal de -1.00.
| |
Esta es la parte final del Unit Testing. Ten en cuenta que usando todos estos poderosos conocimientos, podremos lograr crear Unit Tests de calidad para nuestras aplicaciones en Java.