Las funciones tipo query, es decir, que tienen un return, por lo general son muy fáciles de testear, porque siempre devuelven un resultado.
Pero ¿qué ocurre cuando queremos testear una función tipo action?
Vamos a poner un ejemplo:
Imaginemos que estamos testeando esta función. Esta función es un constructor que nos devuelve un método que calcula la operación que le indiquemos. En este caso, sólo ejecuta las sumas, pero nos vale para el ejemplo.
Nuestra función constructora recibe como parámetro un client, que es otra función que tiene un método que, como vemos aquí, se llama save.
Ahora no estamos testeando al archivo client, ni sus métodos, por lo que no vamos a desarrollar lo que tiene esa función. Lo que queremos testear es nuestro constructor createServiceClient y, en concreto, su método calculate.
Ahora bien, ¿cómo testeamos ese método save, que es ajeno a nosotros? ¿Cómo comprobamos que el método calculate hace correctamente cada una de sus líneas y en concreto esa de la que no tenemos control desde aquí?
Se trata de un action, porque no tiene un return, sino que sólo ejecuta algo, en ese caso, supuestamente, guardar el resultado.
Espías en testing
Para abordar este problema, lo que vamos a hacer es espiar ese método, inyectándole un objeto. ¿Y eso cómo se hace?
El primer test es el que comprueba la suma, pero ese no es el que nos interesa ahora. Vamos a fijarnos en el segundo test que comprueba si se ha llamado al cliente para guardar el resultado.
Lo que queremos comprobar entonces no es el resultado de la suma en sí, sino que se ha llamado al método save del client y que se le ha pasado el valor correcto para guardar.
Por eso hemos simulado un método save, que lo único que hace es inyectar un objeto con una propiedad en la que insertamos en resultado para poder realizar las comprobaciones pertinentes. Es decir, nos inventamos lo que hace esa función y usamos ese objeto para comprobar qué valor recibe el método o si lo recibe.
client.save = (result) => {
saveResult = result
};
Esto es lo que se conoce como mock y, en concreto, dentro de los tipos de mocks que hay, es de tipo spy (espía).
Así pues, un mock spy, es una función u objecto que tiene la capacidad de retener cosas que han ocurrido durante la ejecución de la función de la cual es colaborador. En nuestro caso, el método save de la dependencia client, que hemos redefinido en nuestro test, ha retenido el resultado que se obtiene de la ejecución de la función calculate y nos está ayudando a realizar las comprobaciones anteriormente descritas.
Ejemplos by Carlos Blé