El objetivo de una prueba unitaria es probar un solo objeto, pero en ciertas ocasiones las colaboraciones entre objetos tienen un acoplamiento alto por lo tanto no puedo probar un objeto sin llamar a otro. Es aquí donde los test se ensucian un poco, en especial si el objeto que deseamos testear depende de algún objeto “pesado” o que tenga interacción con algún otro sistema externo, servidor o base de datos. Por ejemplo testear un objeto que valide el nombre de usuario y la clave en un ldap.
Una estrategia de solución para este problema es usar objetos mocks, los objetos mocks son objetos “de mentira” que permiten simular otro objeto o entidad del sistema. Si vamos a la wikipedia podremos encontrar la siguiente definición:
En la programación orientada a objetos se llaman objetos simulados (pseudoobjetos, mock object, objetos de pega) a los objetos que imitan el comportamiento de objetos reales de una forma controlada. Se usan para probar a otros objetos en pruebas de unidad que esperan mensajes de una clase en particular para sus métodos, al igual que los diseñadores de autos usan un crash dummy cuando simulan un accidente.
En los test de unidad, los objetos simulados se usan para simular el comportamiento de objetos complejos cuando es imposible o impracticable usar al objeto real en la prueba. De paso resuelve el problema del caso de objetos interdependientes, que para probar el primero debe ser usado un objeto no probado aún, lo que invalida la prueba: los objetos simulados son muy simples de construir y devuelven un resultado determinado y de implementación directa, independientemente de los complejos procesos o interacciones que el objeto real pueda tener.
Existen diferentes frameworks en java para hacer mocks, easymock, mockito, etc. Vamos a utilizar mockito.
Mockito es un framework simple, fácil de usar para hacer objetos mocks en java. Tiene una interfaz simple y natural.
Características:
- Se pueden crear mocks de interfaces y clases concretas.
- Verificación de invocaciones (cantidad exacta, al menos una vez, órden de invocación, etc.)
- El stack trace se mantiene limpio, ya que los errores ocurren en los assert que se hagan (y no dentro del método bajo prueba).
- Un API más clara para crear stubs y verificaciones.
Vamos a hacer un objeto mock con mockito:
//creamos el mock y el stub ArrayList instance = mock(ArrayList.class); doReturn("hola mundo").when(instance).get(0); //ejecutamos la lógica a probar instance.get(0); //verificamos que se hayan invocado los métodos verify(instance).get(0)
Como se puede ver la api es clara y simula el lenguaje natural. En la primera linea creamos un objeto mock de la lista; luego indicamos que cuando se llame el método get con el parámetro 0 debe devolver “hola mundo”. Luego ejecutamos el método y luego se verifica si este método se corrió.
Para agregar este framework a nuestro proyecto maven es solo necesario agregar esta entrada en el pom:
org.mockito mockito-all 1.8.5