Mocks y Otros Dobles de Prueba
Mocks y Otros Dobles de Prueba
Mocks y Otros Dobles de Prueba
Antes de decidirnos a usar objetos mock (en adelante mocks) hay que contar hasta diez y pensarlo
dos veces. Lo primero, es saber en todo momento qué es lo que vamos a probar y por qué. En las
listas de correo a menudo la gente pregunta cómo deben usar mocks para un problema
determinado y buena parte de las respuestas concluyen que no necesitan mocks, sino partir su
test en varios y/o reescribir una parte del SUT. Los mocks presentan dos inconvenientes
fundamentales:
El test corre el riesgo de volverse frágil si conoce demasiado bien el interior del SUT.
Frágil significa que un cambio en el SUT, por pequeño que sea, romperá el test forzándonos a
reescribirlo. La gran ventaja de los mocks es que reducen drásticamente el número de líneas de
código de los tests de validación de interacción y evitan que el SUT contenga hacks (apaños) para
validar.
En los tests de validación de estado, también se usan mocks o stubs cuando hay que acceder a
datos procedentes de un colaborador. Por lo tanto, los mocks (y otros dobles) son imprescindibles
para un desarrollo dirigido por tests completo pero, igualmente importante, es saber cuándo van a
poner en jaque al test, o sea, cuándo debemos evitarlos.
Un mock es un tipo concreto de doble de test. La expresión doble se usa en el mismo sentido de
los actores dobles en las películas de acción, ya que se hace pasar por un colaborador del SUT
cuando en realidad no es la entidad que dice ser. Gerard Meszaros describe los distintos tipos de
dobles de test en su libro donde, además, sienta las bases de la nomenclatura. Martin Fowler
publicó un artículo que se ha hecho muy popular basado en esta nomenclatura; "Los mocks no son
stubs", donde habla de los distintos dobles. De ahí extraemos el siguiente listado de tipos de
doble:
Dummy: se pasa como argumento pero nunca se usa realmente. Normalmente, los objetos
dummy se usan sólo para rellenar listas de parámetros.
Fake: tiene una implementación que realmente funciona pero, por lo general, toma algún atajo o
cortocircuito que le hace inapropiado para producción (como una base de datos en memoria por
ejemplo).
Stub: proporciona respuestas predefinidas a llamadas hechas durante los tests, frecuentemente,
sin responder en absoluto a cualquier otra cosa fuera de aquello para lo que ha sido programado.
Los stubs pueden también grabar información sobre las llamadas; tal como una pasarela de email
que recuerda cuántos mensajes envió.
El stub es como un mock con menor potencia, un subconjunto de su funcionalidad. Mientras que
en el mock podemos definir expectativas con todo lujo de detalles, el stub tan sólo devuelve
respuestas preprogramadas a posibles llamadas. Un mock valida comportamiento en la
colaboración, mientras que el stub simplemente simula respuestas a consultas.
El stub hace el test menos frágil pero, al mismo tiempo, nos aporta menos información sobre la
colaboración entre objetos. Para poder discernir entre usar un mock o un stub, volvemos a
recalcar que primero hay que saber qué estamos probando y por qué. Los mocks tienen ventajas e
inconvenientes sobre los stubs. Lo mejor será mostrarlas con ejemplos.
Los frameworks que generan mocks y stubs son muy ingeniosos. Son capaces de crear una clase en
tiempo de ejecución, que hereda de una clase X o que implementa una interfaz Y. Tanto X como Y
se pueden pasar como parámetro para que el framework genere una instancia de un mock o un
stub que sea de ese tipo pero cuya implementación simplemente se limita a reaccionar tal como le
indiquemos que debe hacerlo.
En este libro usaremos el framework Rhino.Mocks versión 3.6 para .Net, EasyMock 2.5.2 para Java,
Mockito 1.8.2 para Java y Pymox 0.5.1 para Python. Todos son software libre y se pueden
descargar gratuitamente de la red.
Este capítulo posiblemente sea de los más difíciles de entender de todo el libro. Para una correcta
comprensión del mismo es recomendable leerlo con el ordenador delante para ir ejecutando los
ejemplos.