Saltar al contenido

Etiqueta: pruebas unitarias

Class already exists en PHPUnit

Esta semana en el trabajo me topé con un error de Class already exists en PHPUnit. El cual me sorprendió porque no tenía mucho sentido:

Mockery\Exception\RuntimeException: Could not load mock class MiClase: class already exists

Entonces lo primero que pensé fue: “¡¿Cómo que ya existe si lo acabo de crear?!”. En mi trabajo estábamos creando una serie de pruebas unitarias (como siempre me ha gustado) para una nueva funcionalidad bastante grande, y usamos Mockery como herramienta para simular el comportamiento de clases y objetos. Si no lo conoces, Mockery es una librería para PHP que permite crear mocks, stubs y spies para probar clases de forma aislada, sin tener que depender de la implementación real.

¿Qué es un mock?

Tal vez te preguntes, ¿qué es eso de un mock? Bueno, imagina que tienes una clase llamadaServicioFactura que depende de ServicioCorreo para enviar correos. Pues resulta que cuando haces pruebas unitarias, no quieres que se envíen correos reales (que ningún usuario, inclusive el que está probando, reciba 30 notificaciones de prueba), tanto por costo, como por rendimiento y porque no se esta probando los correos. Entonces usas un mock de CorreoService que simula su comportamiento: no manda correos, pero finge que sí, y hasta puedes verificar si fue llamado o no. Bien útil. De esta forma, cuando se ejecuta la prueba, se ejecutará el mock e intercepta las llamadas y simula el comportamiento original.

Cómo solucionar: Class already exists en PHPUnit

Volviendo al error de Class already exists en PHPUnit, en el fondo, lo que pasaba es que tenia un conflicto con la instancia de un mock ya definido, es decir, habia definido un mock de una instancia de esa clase y aparte otro para la clase. . Si te estás preguntando qué es un mock de una instancia, son algo como esto:

$mock = mock('overload:' . MI_CLASE_MOCKEADA::class);

Cuando mezclas un instance mock con un mock normal, lo que en realidad estás haciendo es intentar redefinir la misma clase dos veces. Y eso ocasiona el error mencionado.

La solución a largo plazo es refactorizar ese código viejo para que nuestros tests no dependan de instance mocks. Pero la solución rápida y sencilla, es ejecutar cualquier prueba que use un instance mock en un proceso separado. PHPUnit hace esto muy fácil con una simple anotación:

/**
 * @runInSeparateProcess
 * @preserveGlobalState disabled
 */
public function pruebaQueIncluyeLosMockupsDeInstancia(): void
{
    // código con los mocks de instancia
}

Ya con eso deberías poder ejecutar la prueba, si necesitas mas información puedes ver la documentación oficial de PHP.Unit. Y si sigues con el problema, puedes probar con cerrar los mocks después de cada test con:

protected function tearDown(): void
{
    Mockery::close();
}

Palabras finales

¿Te ha pasado algo parecido? ¿Tienes otra solución o teoría? ¡Déjamelo en los comentarios, me encantaría leerte!

Gracias por leer hasta el final. Si te encontraste con el error Class already exists en PHPUnit y llegaste hasta aquí buscando respuestas, espero que esto haya sido útil.

Happy Testing! 🧪✨

Deja un comentario

Unit Testing Principles, Practices, and Patterns: libro para iniciarte en el testing

Hace un par de años, me embarqué en la búsqueda de formas para potenciar mis habilidades en pruebas de software. Fue en un hilo de Twitter (ahora X) donde me topé con una discusión sobre las diferencias entre stub y mock. En medio de esta conversación, alguien recomendó el libro «Unit Testing Principles, Practices, and Patterns» de Vladimir Khorikov. Después de haber adquirido el libro hace algún tiempo, finalmente encontré el momento oportuno para sumergirme en sus páginas y, en este artículo, compartiré mis impresiones al respecto.

Portada del libro Unit Testing Principles, Practices, and Patterns de Vladimir Khorikov
Portada del libro, si deseas comprarlo haz clic en él para mas información

Contenido de Unit Testing Principles, Practices, and Patterns

En mi opinión, el libro abarca todo lo necesario para aprender a aplicar pruebas a cualquier software que desarrolles. Desde las razones fundamentales para realizar pruebas hasta conceptos como unit testing, mocks, test doubles, integration testing, end to end tests, entre otros. Además, finaliza con una sección muy interesante sobre anti-patrones, la cual nos brinda valiosas enseñanzas para mejorar nuestras prácticas de codificación y hacer que el código sea más accesible de probar.

Cada sección comienza con la presentación del concepto, seguido de su aplicación en el ámbito profesional. Posteriormente, se ofrece una serie de ejemplos de código que abarcan tanto el método o sección de código a probar como el código de las pruebas correspondientes. Este enfoque estructurado garantiza una comprensión completa y práctica de los temas tratados.

Es importante destacar que si bien los ejemplos de código están escritos en Java, su estructura y lógica son fácilmente transferibles a otros lenguajes de programación como PHP o C++. Cualquier profesional, independientemente de su preferencia de lenguaje de programación podrá leer los ejemplos sin problemas.

Además, el texto cuenta con secciones que contienen notas sobre consideraciones importantes a tener en cuenta, así como experiencias personales del autor frente a diversas situaciones. Esta combinación de teoría, ejemplos prácticos y reflexiones personales enriquece la experiencia de aprendizaje y ofrece una perspectiva más completa sobre el proceso de pruebas de software.

¿Debería leerlo?

Este libro es verdaderamente accesible para personas de todos los niveles de experiencia. Ya seas un principiante absoluto o un profesional experimentado en el campo de las pruebas de software, encontrarás que Unit Testing Principles, Practices, and Patterns ofrece valiosos conocimientos y perspectivas. En definitiva, si deseas adentrarte en el mundo del testing o mejorar tus habilidades existentes, este libro es para ti.

Deja un comentario