Volver a la página principal
viernes 16 agosto 2024
71

Cómo hacer tests en Laravel utilizando Mockery

¿Qué es Mockery?

Mockery es una biblioteca de PHP que permite crear mocks (objetos simulados) para realizar pruebas unitarias. Un mock es un objeto que simula el comportamiento de otro objeto real en un entorno controlado. Esto es particularmente útil cuando se necesita aislar la lógica que se desea probar de sus dependencias externas, como bases de datos, servicios externos, o incluso otras clases dentro de la misma aplicación.

Ventajas de usar Mockery en Laravel

1. Aislamiento de pruebas: Al usar mocks, se pueden aislar las pruebas unitarias para asegurarse de que solo se está probando la lógica específica de la clase o método en cuestión.

2. Simulación de dependencias complejas: Mockery permite simular dependencias complicadas o difíciles de configurar, como servicios externos o bases de datos.

3. Control de comportamiento: Con Mockery, puedes definir cómo deben comportarse los mocks en diferentes escenarios, incluyendo excepciones y respuestas específicas.

Instalación de Mockery en un Proyecto Laravel

Antes de poder utilizar Mockery en tus tests de Laravel, necesitas asegurarte de que la biblioteca esté instalada en tu proyecto. Puedes instalar Mockery mediante Composer:

composer require --dev mockery/mockery

Esta instrucción añade Mockery como una dependencia de desarrollo en tu proyecto. Dado que Laravel ya integra PHPUnit, no es necesario instalarlo por separado.

Configuración Inicial

Una vez instalada, Mockery puede ser utilizado directamente en tus tests. Sin embargo, es recomendable configurarlo para que se integre bien con PHPUnit, lo que facilita su uso y gestión de mocks en cada prueba.

Abre el archivo phpunit.xml en la raíz de tu proyecto Laravel y asegúrate de que Mockery se utiliza correctamente al finalizar cada test:

<php>
    <env name="APP_ENV" value="testing"/>
    <env name="CACHE_DRIVER" value="array"/>
    <env name="SESSION_DRIVER" value="array"/>
    <env name="QUEUE_DRIVER" value="sync"/>
    <env name="MAIL_MAILER" value="array"/>
    <env name="TELESCOPE_ENABLED" value="false"/>
    <env name="LOG_CHANNEL" value="errorlog"/>
</php>

A continuación, vamos a examinar cómo puedes utilizar Mockery en algunos ejemplos prácticos.

Ejemplo Básico de Uso de Mockery en Laravel

Imagina que tienes un servicio que depende de una clase PaymentGateway para procesar pagos. Quieres probar un método processPayment en tu clase OrderService, pero no deseas realizar una transacción real durante la prueba. Aquí es donde Mockery resulta útil.

Paso 1: Crear un Mock

use Mockery;
use PHPUnit\Framework\TestCase;

class OrderServiceTest extends TestCase
{
    public function testProcessPayment()
    {
        // Crear un mock de PaymentGateway
        $paymentGatewayMock = Mockery::mock(PaymentGateway::class);

        // Configurar el mock para que el método `charge` devuelva true
        $paymentGatewayMock->shouldReceive('charge')
                           ->once()
                           ->with(1000)
                           ->andReturn(true);

        // Inyectar el mock en OrderService
        $orderService = new OrderService($paymentGatewayMock);

        // Ejecutar el método a probar
        $result = $orderService->processPayment(1000);

        // Verificar el resultado
        $this->assertTrue($result);
    }

    // Destruir los mocks después de cada test
    public function tearDown(): void
    {
        Mockery::close();
        parent::tearDown();
    }
}

Explicación del Código

1. Crear un Mock: Utilizamos Mockery::mock(PaymentGateway::class) para crear un mock de la clase PaymentGateway.

2. Configurar el Mock: Definimos que el método charge será llamado una vez con un argumento de 1000, y devolverá true.

3. Inyectar el Mock: Inyectamos el mock en OrderService, lo que nos permite simular el comportamiento de PaymentGateway sin realizar una transacción real.

4. Ejecutar y Verificar: Ejecutamos el método processPayment y verificamos que el resultado sea true.

5. Cerrar Mockery: Al final de cada test, llamamos a Mockery::close() para asegurar que no haya mocks residuales.

Ejemplo Avanzado: Simulando Excepciones

Supongamos que el método charge puede lanzar una excepción en caso de error. Queremos probar que nuestro OrderService maneja correctamente esta excepción.

Paso 1: Crear un Mock que Lance una Excepción

use Mockery;
use PHPUnit\Framework\TestCase;

class OrderServiceTest extends TestCase
{
    public function testProcessPaymentHandlesException()
    {
        // Crear un mock de PaymentGateway
        $paymentGatewayMock = Mockery::mock(PaymentGateway::class);

        // Configurar el mock para que lance una excepción
        $paymentGatewayMock->shouldReceive('charge')
                           ->once()
                           ->with(1000)
                           ->andThrow(new PaymentFailedException);

        // Inyectar el mock en OrderService
        $orderService = new OrderService($paymentGatewayMock);

        // Ejecutar el método a probar y verificar que la excepción es manejada
        $result = $orderService->processPayment(1000);

        $this->assertFalse($result);
    }

    public function tearDown(): void
    {
        Mockery::close();
        parent::tearDown();
    }
}

Explicación del Código

1. Lanzar una Excepción: Usamos andThrow para indicar que el método charge debe lanzar una PaymentFailedException cuando sea llamado.

2. Manejo de la Excepción: En nuestro test, verificamos que processPayment devuelve false cuando se lanza la excepción.

Mejores Prácticas al Usar Mockery en Laravel

1. Cerrar Mockery: Siempre cierra Mockery después de cada test utilizando Mockery::close(). Esto asegura que no haya efectos secundarios no deseados.

2. Mocks Específicos: Crea mocks solo para las dependencias que realmente necesitas simular. Evita crear mocks de todo, ya que esto puede llevar a pruebas menos fiables.

3. Verificar Interacciones: Utiliza shouldReceive() y once() para verificar que los métodos se llamen el número correcto de veces y con los argumentos adecuados.

Conclusión

Mockery es una herramienta poderosa que facilita la creación de pruebas unitarias en Laravel al permitir la simulación de dependencias complejas. Al dominar su uso, puedes aislar mejor la lógica de tu aplicación y asegurar que tus pruebas sean más precisas y confiables.

Utilizar Mockery en conjunto con Laravel y PHPUnit no solo mejora la calidad de tus pruebas, sino que también te permite desarrollar con mayor confianza, sabiendo que tu código ha sido probado rigurosamente en un entorno controlado. ¡Empieza a implementar Mockery en tus pruebas hoy mismo y lleva la calidad de tu código al siguiente nivel! 😃🙂

Compartir:
Creado por:
Author photo

Jorge García

Fullstack developer