Java Mockito es uno de los frameworks de Mock más utilizados en la plataforma Java. Esto es debido a la gran facilidad de uso que tiene. Vamos a intentar explicar el concepto de Mock y como funciona Java Mockito , para ello construiremos unos test sencillos partiendo de dos clases de Servicio que se encuentran relacionadas. Recordemos que muchas metodologías apoyan generar los test primero ,pero aquí nos vamos a centrar en los conceptos.
En este caso una clase se encarga de sumar dos números y la otra se encarga de multiplicarlos.
public interface ServicioA { public abstract int sumar(int a, int b); }
package com.arquitecturajava.servicios; public class ServicioAImpl implements ServicioA { public int sumar(int a ,int b) { return a+b+1; } }
package com.arquitecturajava.servicios; public interface ServicioB { public ServicioA getServicioA(); public void setServicioA(ServicioA servicioA); public int multiplicarSumar(int a, int b, int multiplicador); public int multiplicar(int a, int b);
package com.arquitecturajava.servicios; public class ServicioBImpl implements ServicioB { private ServicioA servicioA; public ServicioA getServicioA() { return servicioA; } public void setServicioA(ServicioA servicioA) { this.servicioA = servicioA; } public int multiplicarSumar(int a ,int b,int multiplicador) { return servicioA.sumar(a, b)*multiplicador; } public int multiplicar(int a ,int b) { return a*b; } }
Como podemos observar ambas clases disponen de un método que se puede testear de forma aislada ServicioA (sumar) y ServicioB (multiplicar). Vamos a instalar JUnit y Mockito como dependencias de Maven para poder trabajar.
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.arquitecturajava</groupId> <artifactId>mocks</artifactId> <version>0.0.1-SNAPSHOT</version> <name>mocks</name> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> </dependency> <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-core</artifactId> <version>1.10.19</version> </dependency> </dependencies> </project>
Construimos los test :
package com.arquitecturajava.test; import org.junit.Assert; import org.junit.Test; import com.arquitecturajava.servicios.ServicioA; import com.arquitecturajava.servicios.ServicioAImpl; public class TestServicioA { @Test public void testSuma() { int a=2; int b=2; ServicioA servicio= new ServicioAImpl(); Assert.assertEquals(servicio.sumar(a, b),4); } }
package com.arquitecturajava.test; import org.junit.Assert; import org.junit.Test; import com.arquitecturajava.servicios.ServicioA; import com.arquitecturajava.servicios.ServicioAImpl; import com.arquitecturajava.servicios.ServicioB; import com.arquitecturajava.servicios.ServicioBImpl; public class TestServicioB { @Test public void testMultiplicacion() { ServicioB servicioB= new ServicioBImpl(); Assert.assertEquals(servicioB.multiplicar(2, 3),6); }
Ejecutamos ambos Test con JUnit :
Ahora bien ¿qué pasará si tenemos que testear el método sumarMultiplicar que tiene el ServicioB?. Este método primero suma dos números delegando en el ServicioA y luego los multiplica.
@Test public void testmultiplicarSumar() { ServicioA servicioA=new ServicioAImpl(); ServicioB servicioB= new ServicioBImpl(); servicioB.setServicioA(servicioA); Assert.assertEquals(servicioB.multiplicarSumar(2, 3, 2),10); }
Todo funciona correctamente. Los problemas aparecen cuando yo modifico el método sumar del ServicioA y le asigno el siguiente código:
package com.arquitecturajava.servicios; public class ServicioAImpl implements ServicioA { public int sumar(int a ,int b) { return a+b+1; } }
Los test fallarán:
Fallan dos test y no uno solo, esto es un problema importante ya que los desarrolladores no sabrán que esta pasando exactamente. Para evitar este tipo de problemas debemos aislar las pruebas unitarias y una de las opciones es usar Java Mockito y crear un Mock Object. Los objetos Mock nos permiten simular ser un objeto real y eliminan dependencias , permitiendo que los test se ejecuten de forma aislada.
Vamos a ver el código:
@Test public void testmultiplicarSumar() { ServicioA servicioA=mock(ServicioA.class); when(servicioA.sumar(2,3)).thenReturn(5); ServicioB servicioB= new ServicioBImpl(); servicioB.setServicioA(servicioA); Assert.assertEquals(servicioB.multiplicarSumar(2, 3, 2),10); }
Hemos creado un mock que simula ser el ServicioA para la operación de suma(2,3) y devuelve como resultado 5. Si volvemos a ejecutar los test:
Ahora solo falla un test , hemos conseguido aislar cada uno de ellos y los desarrolladores podrán encontrar los errores de forma fácil. Para ello hemos construido un objeto Mock utilizando Java Mockito.
Otros artículos relacionados:
Fantástico Blog… miraré los cursos que hay
gracias 🙂
Buenas.
Muchas gracias por la información, me ha servido.
Veo que hay mucha información interesante por aquí. Hay vídeos y demás. Para acceder a ellos necesito suscribirme? Cuesta algo la suscripción?
Saludos.
Por ahora solo tengo 4 cursos publicados , estoy empezando poco a poco , si te quieres apuntar a alguno , te sugiero que esperes a que salga algún cupón de descuento . O te apuntes de entrada a los gratuitos 🙂
Hola jose . Según entendí la sentencia “return a+b+1;” esta puesta con todo propósito para que el Test falle. Si no quedaria el metodo sumar igual que antes.
Hola Jose, disculpeme. Creo que usted se refiere por primer método sumar, a una versión anterior del articulo que fue corregida.
perdonado ;P
gracias por la correcion
Creo que en el primer método de sumar está erróneo, has puesto return a+b+1; y entiendo que debería ser return a+b; Me gustaría proponerte un artículo. Es sobre realizar un método genérico usando JPA que sirva de consulta básica de una tabla. A partir de una entidad, se genere una consulta según los atributos que vienen informados. Por ejemplo de una entidad Persona vienen indicados nombre y apellidos busque por esos dos campos, si viene por nombre y dni busque por esos otros generando el select. Un método search(T entity) genérico. He buscado el código por internet y no encuentro… Read more »
Gracias por la corrección . Puedes encontrar un Generic DAO en mi libro gratuito de arquitectura java solida 🙂
A ello voy, Cecilio!
Es de agradecer que siempre te tomes la molestia de contestar los comentarios! Sigue así!