Font Size

SCREEN

Profile

Layout

Direction

Menu Style

Cpanel

Aninki Code

Mockito

Mockito es un framework testeo de mocks. Permite escribir pruebas con una API simple.

+ INFO

Mockito - Indice contenidos

 

 

Mockito-introduccion

Mockito es un framework para la creación test de pruebas. Sin embargo, Mockito tiene algunas limitaciones y no es valido para algunos casos:

  • Clases finales
  • Enumerations
  • Métodos finales
  • Métodos estáticos
  • Métodos privados
  • HashCode() y equals

Si necesitamos diferenciar varios conceptos: 

  • Dummy - Un objeto vacío aprobada en una invocación 
  • Fake - Un objeto que tiene una aplicación funciona simplificada
  • Stub - Un objeto hardcodeado
  • Mock- Un objeto con la capacidad de
    • Tienen un programado comportamiento esperado
    • Verificar las interacciones que ocurren 
  • Spy - Una maqueta creada como un proxy para un objeto real existente.

 

Mockito-Creación de un Mock

Quizá la funcionalidad principal de mockito es la creación de Mocks de clases y tener un comportamiento especifico cuando se llama a ciertos metodos.

Os aconsejo que, a la hora de llamar al metodo mock(objeto) para crear el objeto, utilicéis también un segundo parametro llamado Mockito.RETURNS_SMART_NULLS. En caso de resultar un nullpointer, la traza será un poco más legible.

Esto se consigue:

 

private static final Integer TEST_VALOR1 = 1;

	@Test
	public void metodoSinParametros() {
		Ejemplo ejemplo = mock(Ejemplo.class, Mockito.RETURNS_SMART_NULLS);
		when(ejemplo.getValor()).thenReturn(TEST_VALOR8);
		Ejemplo ejemploReal = new Ejemplo();
		assertEquals(ejemplo.getValor().intValue(), ejemploReal.getValor()
				.intValue());

	}

Mockito nos da varios soluciones para los valores a devolver.

thenReturn(T valor a retornar) Nos devuelve un valor en concreto 
thenThrow(Throwable toBeThrown) thenThrow(ClasstoBeThrown)  Devuelve una excepción
then(Answer answer) thenAnswer(Answer answer)  No ejecuta una clase Answer. Ver el ejemplo del código para una mayor comprensión del caso 
  
@Test
	public void metodoConParametros() {
		Ejemplo ejemplo = mock(Ejemplo.class);
		when(ejemplo.getEntrada(TEST_VALOR1)).thenReturn(TEST_VALOR1);
		//lanzamiento de excepciones
		when(ejemplo.getEntrada(null)).thenThrow(new NullPointerException(ERROR_DE_NULL_POINTER));
		
		
		Ejemplo ejemploReal = new Ejemplo();
		assertEquals(ejemplo.getEntrada(TEST_VALOR1).intValue(), ejemploReal
				.getEntrada(TEST_VALOR1).intValue());
		try {
			ejemplo.getEntrada(null);

		} catch (Exception e) {
			
			
			assertEquals(e.getMessage(),
					ERROR_DE_NULL_POINTER);		
		}
		
		//Ejemplo de mock con Answers
		 when(ejemplo.getEntrada(TEST_VALOR2)).thenAnswer(new Answer() {
		     public Object answer(InvocationOnMock invocation) {
		         Object[] args = invocation.getArguments();
		         Object mock = invocation.getMock();
		         return TEST_VALOR3;
		     }
		 });
		 
                 //ejemplo creando un custom Answer
		 when(ejemplo.getEntrada(TEST_VALOR8)).thenCallRealMethod();
			assertEquals(ejemplo.getEntrada(TEST_VALOR8).intValue(), ejemploReal
					.getEntrada(TEST_VALOR8).intValue());
		 
		 assertEquals(ejemplo.getEntrada(TEST_VALOR2),TEST_VALOR3);
	}


 

 

Mockito-Verificación de llamadas

Mockito también nos permite verificar si se han producido las llamadas a los métodos y permitir ciertas aserciones, de manera que podemos comprobar si nuestro método ha sido llamada o no.

Esto se consigue:

 

private static final Integer TEST_VALOR1 = 1;

	@Test
	public void testVerify(){
		Ejemplo ejemplo = mock(Ejemplo.class);
		
		ejemplo.getCadenaEntrada("1");	
		
		//verificamos que se le ha llamado
		verify(ejemplo).getCadenaEntrada("1");
		//verificamos que se le ha llamado 2 veces
		 verify(ejemplo,times(1)).getCadenaEntrada("1");	
		//verificamos que se le ha llamado por lo menos 1 vez
		verify(ejemplo,atLeastOnce()).getCadenaEntrada("1");
		//como mucho 3 tres veces no mas
		verify(ejemplo, atMost(5)).getCadenaEntrada("1");
		//solo se le hallamdo al 1
		verify(ejemplo, only()).getCadenaEntrada("1");
		//verify el time out
		verify (ejemplo,timeout(20000)).getCadenaEntrada("1");
	
	}

También podemos saber en qué order se han producido las llamadas al mock y que valor se han ejecutado :

	@Test
	public void testOrder(){
		Ejemplo ejemplo = mock(Ejemplo.class);
		Ejemplo ejemplo1 = mock(Ejemplo.class);
		
		ejemplo.getValor();
		ejemplo1.getCadenaEntrada("cadena");
		//checkeamos el orden de las llamadas
		InOrder inOrder = inOrder(ejemplo, ejemplo1);
		inOrder.verify(ejemplo).getValor();
		inOrder.verify(ejemplo1).getCadenaEntrada("cadena");
		
	}

Mockito-Verificación llamadas a objetos reales

Con Mockito también podemos hacer mocks de ciertas partes de nuestro código. Es decir, hacemos un mock de ciertas partes del objeto y otras partes del objeto las dejamos si modificar.

Para ello seguimos con nuestros ejemplos:

 

private static final Integer TEST_VALOR1 = 1;

	@Test
	public void testVerify(){
		Ejemplo ejemplo = mock(Ejemplo.class);
		
		ejemplo.getCadenaEntrada("1");	
		
		//verificamos que se le ha llamado
		verify(ejemplo).getCadenaEntrada("1");
		//verificamos que se le ha llamado 2 veces
		 verify(ejemplo,times(1)).getCadenaEntrada("1");	
		//verificamos que se le ha llamado por lo menos 1 vez
		verify(ejemplo,atLeastOnce()).getCadenaEntrada("1");
		//como mucho 3 tres veces no mas
		verify(ejemplo, atMost(5)).getCadenaEntrada("1");
		//solo se le hallamdo al 1
		verify(ejemplo, only()).getCadenaEntrada("1");
		//verify el time out
		verify (ejemplo,timeout(20000)).getCadenaEntrada("1");
	
	}

También podemos saber en qué order se han producido las llamadas al mock y qué valor se han ejecutado :

		@Test
	public void testSpyObject(){
		//Objeto Real
		 Ejemplo ejemplo=new Ejemplo();
		 //Objeto mockeado
		 Ejemplo ejemploSpy = org.mockito .Mockito.spy(ejemplo);

		 org.mockito.BDDMockito.willDoNothing().given(ejemploSpy).setValor(TEST_VALOR3);
				 
		 ejemploSpy.setValor(TEST_VALOR3);		 
		 assertEquals(ejemploSpy.getValor(), ejemplo.VALOR); //value was not

	}

Mockito - Argument Maching

Este método nos permite definir las distintas respuestas que tendrá un mock en función de los distintos tipos de entrada.

	private static final String LO_TENGO = "LO TENGO";
	private static final String ERROR_DE_NULL_POINTER = "Error de null Pointer";
	private static final Integer TEST_VALOR1 = 1;
	private static final Integer TEST_VALOR2 = 2;
	private static final Integer TEST_VALOR3 = 3;
	private static final Integer TEST_VALOR4 = 4;
	private static final Integer TEST_VALOR8 = 8;
	private static final String ANY_STRING_EXAMPLE = "ANY_STRING_EXAMPLE";

...
	@Test
	public void ArgumentMaching(){
		Ejemplo ejemplo = mock(Ejemplo.class);
		//BDDMockito. Behavior driven development
		org.mockito.BDDMockito.given(ejemplo.getEntrada(TEST_VALOR2)).willReturn(TEST_VALOR3);
		assertEquals(ejemplo.getEntrada(TEST_VALOR2),TEST_VALOR3);
		
               //tenemos varias posible opciones : argThat, anyInt...
		org.mockito.BDDMockito.given(ejemplo.getCadenaEntrada(org.mockito.Matchers.anyString())).willReturn(ANY_STRING_EXAMPLE);
		
		assertEquals(ejemplo.getCadenaEntrada(ANY_STRING_EXAMPLE),ANY_STRING_EXAMPLE);
		
		
		
		org.mockito.BDDMockito.given(ejemplo.getCadenaEntrada(org.mockito.Matchers.argThat(cadenaIgual(ANY_STRING_EXAMPLE)))).willReturn(LO_TENGO);
		assertEquals(ejemplo.getCadenaEntrada(ANY_STRING_EXAMPLE),(LO_TENGO));
	
	}


     // un magument macher.Solo se utiliza en el caso qu utilicemos argThat en lugar de any()....
	private ArgumentMatcher cadenaIgual(final String cadena) {
	return new ArgumentMatcher() {
		@Override
		public boolean matches(Object argument) {
			return "ANY_STRING_EXAMPLE".equals((String)argument);
		}
	};
	}

A continuación os dejo un cuadro con los posibles argumentos:

 

any(), any(Classclazz) Cualquier clase o paremetro de entrada. Incluye null
anyBoolean(), anyByte(), anyChar(), anyDouble(), anyFloat(), anyInt(), anyLong(), anyShort(), anyString() Cualquier objeto del tipo del método
anyCollection(), anyList(),anyMap(), anySet() Cualquier colección de las especificadas
  Cualquier colección de los tipos determinados
eq(T value) Cualquier objeto que sea equals
isNull, isNull(Classclazz) Valores nulos
isNotNull, isNotNull(Classclazz) Valores no nulos
   
isA(Classclazz) Clase que sea del tipo definido (Puede ser por herencia)
matches(String regex) String que cumple la expresión regular
startsWith(string), endsWith(string), contains(string) String que cumple las condiciones
aryEq(PrimitiveType value[]), aryEq(T[] value) Array que es equivalente al array de entrada
cmpEq(Comparablevalue) Cualquier método igual usando un Comparator
gt(value), geq(value), lt(value), leq(value) for primitive types and Comparable Argumentos que cumplan greater,equals,less
anyVararg() Cualquier varargs

 

El resumen de esta tabla ha sido obtenido en Mockito - RefcardZ (dzone.com) 

Mockito - Test métodos Void

Testear métodos void, es algo diferente:

	@Test
	public void mockVoidMethods(){
		//void methods
		Ejemplo ejemplo = mock(Ejemplo.class);
		org.mockito.BDDMockito.doThrow(new NullPointerException()).when(ejemplo).getValor();
		try{
			ejemplo.getValor();
			assertEquals(1,2);
		}catch (NullPointerException e){
			return;
		}
	
	}

También es posible devolver diferentes mocks en función según si es la primera, segundo o sucesivas llamadas

		
       @Test
	public void mockMultipleTimes(){
	//	el segundo parametro es el segundo valor
		Ejemplo ejemplo = mock(Ejemplo.class);
		//la primera vez llama a 1 la segunda a 5
		org.mockito.BDDMockito.given(ejemplo.getEntrada(TEST_VALOR1)).willReturn(TEST_VALOR1,TEST_VALOR3);
	
		
		org.mockito.BDDMockito.given(ejemplo.getEntrada(TEST_VALOR1)).willReturn(TEST_VALOR1,TEST_VALOR3);
		
	
	}

Mockito - Anotaciones

Mockito nos permite crear anotaciones.Es importante que, despues de injectados los métodos, llamar al método MockitoAnnotations.initMocks(this);

        @Mock 
	private Ejemplo ejemploAnotado;	
     //@Mock con smart nulls 
     @Mock(answer = Answers.RETURNS_SMART_NULLS)
     private Ejemplo ejemploAnotado3;	
 
	@Spy
	private Ejemplo ejemploSyyAnotado;	
	@InjectMocks
	private Ejemplo mockInjectado;	

.....

	@Test
	public void mockitoAnotations(){
		
		MockitoAnnotations.initMocks(this);
		assertNotNull(ejemploAnotado);
		assertNotNull(ejemploSyyAnotado);
		assertNotNull(mockInjectado);
		

	}