Pruebas en PHP: Unit, Integration, E2E a nivel avanzado

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

Pruebas en PHP: Unit, Integration, E2E a nivel avanzado



En el desarrollo web moderno con PHP, la calidad del código ha dejado de ser una opción: es una condición obligatoria para la supervivencia del proyecto. Las pruebas unitarias básicas son familiares para todo desarrollador, pero tan pronto como el proyecto supera los límites de "Hello World", surge la necesidad de enfoques más complejos: pruebas de integración, verificación de la interacción de componentes y pruebas de extremo a extremo (E2E) de escenarios de usuario.



Este artículo está dirigido a desarrolladores PHP de nivel Middle y superior, que ya están familiarizados con PHPUnit y desean profundizar sus conocimientos. Analizaremos técnicas avanzadas: pruebas con dependencias externas, trabajo con contenedores de prueba, aislamiento de infraestructura y construcción de una estrategia de pruebas completa.



1. Pruebas Unitarias Avanzadas: Objetos Mock y Stubs



A nivel avanzado, las pruebas unitarias dejan de ser simplemente la verificación de funciones matemáticas. Prueban la lógica de negocio, aislada del mundo exterior. Las herramientas clave son Mock y Stub.



Stub devuelve datos predefinidos. Mock verifica cómo se llamaron exactamente los métodos (número de llamadas, orden de argumentos).



Consideremos un ejemplo: un servicio de pago que envía una solicitud a una pasarela de pago.



<?phpclass PaymentService {    public function __construct(        private PaymentGatewayInterface $gateway,        private LoggerInterface $logger    ) {}

public function processPayment(Order $order): bool { $result = $this->gateway->charge( $order->getAmount(), $order->getCurrency() );

if ($result->isSuccess()) { $this->logger->info('Payment processed', ['order_id' => $order->getId()]); return true; }

$this->logger->warning('Payment failed', ['error' => $result->getError()]); return false; }}

// Prueba con PHPUnitclass PaymentServiceTest extends TestCase { public function testSuccessfulPaymentLogsInfo(): void { // Creamos un Stub para la pasarela $gatewayStub = $this->createStub(PaymentGatewayInterface::class); $gatewayStub->method('charge') ->willReturn(new PaymentResult(true));

// Creamos un Mock para el logger (verificamos la llamada) $loggerMock = $this->createMock(LoggerInterface::class); $loggerMock->expects($this->once()) ->method('info') ->with('Payment processed', $this->arrayHasKey('order_id'));

$service = new PaymentService($gatewayStub, $loggerMock); $result = $service->processPayment(new Order(100, 'USD'));

$this->assertTrue($result); }}


Técnica avanzada: use willReturnCallback() para respuestas dinámicas y withConsecutive() para verificar la secuencia de llamadas.



2. Pruebas de Integración: Base de datos y API externas



Las pruebas de integración verifican cómo su código interactúa con componentes reales: base de datos, sistema de archivos, caché. Aquí no se puede confiar en mocks: se necesita infraestructura real.



Problema: las pruebas se vuelven lentas y frágiles. Solución: usar contenedores de prueba (Testcontainers) o bases de datos SQLite integradas.



Ejemplo de una prueba de integración para un repositorio de usuarios con Doctrine:



<?phpclass UserRepositoryIntegrationTest extends KernelTestCase {    private EntityManagerInterface $entityManager;    private UserRepository $repository;

protected function setUp(): void { self::bootKernel(); $this->entityManager = self::$kernel->getContainer() ->get('doctrine

Blogs

Book Recommendations