Language:

Buscar

Testing Hexagonal en Laravel

  • Share this:
Testing Hexagonal en Laravel

Si has seguido esta serie hasta ahora, ya tienes una idea clara de cómo separar dominio, aplicación e infraestructura.
Pero surge una pregunta inevitable:

¿Cómo probamos todo esto sin volvernos locos?

la buena noticia es que la arquitectura hexagonal hace que los tests sean más fáciles y rápidos.
La mala noticia es que exige disciplina: hay que saber qué testear en cada capa.


La pirámide de testing

Seguro has visto la famosa pirámide de testing:

piramide.png

  • Tests unitarios en la base (muchos, rápidos).
  • Tests de integración en el medio.
  • Tests end-to-end arriba (pocos, más lentos).

En una arquitectura hexagonal, esta pirámide cobra más sentido que nunca:

  • Dominio → tests unitarios puros.
  • Aplicación → tests unitarios con mocks de repositorios.
  • Infraestructura → tests de integración con Laravel, base de datos, etc.

Testing del Dominio

El dominio es PHP puro. No necesitas Laravel, ni base de datos, ni helpers.
Probarlo es tan fácil como instanciar clases y ejecutar métodos.

Ejemplo:

public function test_user_email_can_be_changed()
{
    $user = new User("Carlos", new Email("carlos@example.com"));
    $user->changeEmail(new Email("nuevo@example.com"));

    $this->assertEquals("nuevo@example.com", $user->email()->value());
}

Ventajas:

  • Rápidos.
  • Confiables.
  • Independientes del framework.

Testing de Casos de Uso

Los casos de uso orquestan lógica.
Aquí lo que hacemos es probarlos con repositorios falsos (in-memory o mocks).

Ejemplo:

public function test_can_register_a_user()
{
    $repository = new InMemoryUserRepository();

    $useCase = new RegisterUserUseCase($repository);

    $dto = new RegisterUserDTO("Ana", "ana@example.com");
    $useCase->execute($dto);

    $this->assertCount(1, $repository->all());
}


¿Qué es un InMemoryRepository?

Una implementación de prueba que guarda datos en memoria.

class InMemoryUserRepository implements UserRepositoryInterface
{
    private array $users = [];

    public function save(User $user): void
    {
        $this->users[] = $user;
    }

    public function all(): array
    {
        return $this->users;
    }

    public function findById(int $id): ?User
    {
        return $this->users[$id] ?? null;
    }
}


Esto evita tener que levantar MySQL o Eloquent para testear.


Testing de Infraestructura

Aquí sí entra Laravel en juego.
Queremos asegurarnos de que nuestros adaptadores (controladores, Eloquent, requests) funcionan bien.

Ejemplo de test de integración con Eloquent:

public function test_can_persist_user_with_eloquent_repository()
{
    $repository = new EloquentUserRepository();

    $user = new User("Luis", new Email("luis@example.com"));
    $repository->save($user);

    $this->assertDatabaseHas('users', [
        'email' => 'luis@example.com'
    ]);
}

Y un test de controlador:

public function test_can_register_user_via_http()
{
    $response = $this->postJson('/users/register', [
        'name' => 'Marta',
        'email' => 'marta@example.com'
    ]);

    $response->assertStatus(200)
             ->assertJson(['message' => 'Usuario registrado correctamente']);
}

Ventajas de testear en hexagonal

  • Velocidad: la mayoría de los tests no necesitan framework ni base de datos.
  • Aislamiento: puedes probar tu dominio y casos de uso sin dependencias externas.
  • Confianza: cuando algo falla en producción, sabes si es problema del dominio, de aplicación o de infraestructura.

Errores comunes

  1. Hacer todos los tests en Laravel
    → Lentísimo. Si tu test tarda 5 segundos en correr, algo anda mal.
  2. No probar el dominio aislado
    → Si tu dominio depende de Laravel, ya no es hexagonal.
  3. Confiar solo en tests end-to-end
    → Son útiles, pero no te dicen dónde está el fallo.

Conclusión

El testing en arquitectura hexagonal es un cambio de chip:

  • La mayoría de tus tests son unitarios, rápidos y sin framework.
  • Laravel queda relegado a pruebas de integración y end-to-end.
  • Tu código se vuelve más confiable y menos dependiente del entorno.

En el próximo artículo veremos el proyecto completo con CRUD hexagonal en Laravel, donde uniremos todas las piezas que hemos visto hasta ahora.

Carlos Santiago

Carlos Santiago

Laravel Developer