Por qué utilizar mocks
Al escribir pruebas hay procesos que no queremos ejecutar de verdad: enviar correos, leer o escribir la caché, llamar a APIs externas… Sustituirlos por «impostores que se hacen pasar por lo real» se llama mocking. Ventajas de usar mocks:- Los tests son rápidos: no se ejecutan servicios externos ni operaciones lentas, así que terminan enseguida.
- Los tests son estables: no dependen del estado de un servicio externo y siempre dan el mismo resultado.
- El alcance del test queda claro: verificas una única clase o método.
Objetos mock
Para mockear un objeto que se inyecta a través del contenedor, registra la instancia mock en él. Así, el contenedor usa el mock en lugar de crear el objeto real.Método mock()
El método mock() de la clase base de tests de Laravel hace lo mismo con menos código.
Método partialMock()
Si solo quieres mockear algunos métodos, utiliza partialMock(). Los que no se mockeen se ejecutan con normalidad.
Método spy()
Un spy es parecido a un mock, pero verifica la interacción después de ejecutar el código.
Mientras que en un mock defines de antemano «este método debería llamarse», con un spy compruebas a posteriori «¿se ha llamado este método?».
Mockear facades
A diferencia de las llamadas estáticas normales, los facades sí se pueden mockear. Ofrecen la misma testabilidad que la inyección de dependencias con una sintaxis mucho más concisa. Considera este controlador que utiliza la caché.Cache::get, usa expects().
Spies de facade
Para monitorizar un facade con un spy, llama a su métodospy().
Es útil cuando quieres verificar la interacción tras ejecutar el código.
Manipulación del tiempo
Cuando pruebas lógica que depende del tiempo, resulta útil poder cambiar la hora que devuelvennow() o Carbon::now().
La clase base de los feature tests de Laravel incluye helpers para manipular el tiempo.
travel(): viajar en el tiempo
Viaje temporal con closures
Si pasas una closure a los métodos de viaje, el tiempo queda congelado en el instante indicado durante su ejecución y, al terminar, vuelve al momento original.freezeTime(): detener el tiempo
freezeTime() fija la hora actual. freezeSecond() fija la hora al inicio del segundo actual.
Ejemplo práctico: bloquear hilos inactivos
Manipular el tiempo es útil, por ejemplo, para probar funcionalidades como el bloqueo de un hilo de foro tras un periodo de inactividad.Los métodos como
travel() solo pueden usarse en feature tests (clases que heredan de Tests\TestCase). No están disponibles en el TestCase base de PHPUnit.