Teste de Integração PHP com Docker: Nível Avançado
O teste de integração é uma etapa crítica do desenvolvimento, especialmente para aplicações PHP complexas que interagem com bancos de dados, filas, APIs externas e outros serviços. O Docker permite criar um ambiente isolado, o mais próximo possível da produção, e executar testes em condições reproduzíveis. Neste artigo, abordaremos técnicas avançadas: organização de contêineres de teste, simulação de dependências externas, execução paralela e integração com CI/CD.
1. Arquitetura do ambiente de teste com docker-compose
Para testes de integração, usamos um docker-compose.test.yml separado, que sobe apenas os serviços necessários: PHP-FPM com o código de teste, banco de dados (por exemplo, PostgreSQL), Redis e, opcionalmente, um servidor mock para APIs externas.
version: '3.8'services: php-test: build: context: . dockerfile: Dockerfile.test volumes: - .:/var/www/html environment: DATABASE_URL: "pgsql://test:test@db-test:5432/testdb" REDIS_URL: "redis://redis-test:6379" EXTERNAL_API_URL: "http://mock-server:1080" depends_on: - db-test - redis-test - mock-server
db-test: image: postgres:15-alpine environment: POSTGRES_DB: testdb POSTGRES_USER: test POSTGRES_PASSWORD: test ports: - "5433:5432" # Evita conflito com o BD principal
redis-test: image: redis:7-alpine ports: - "6380:6379"
mock-server: image: mockserver/mockserver:latest environment: MOCKSERVER_PROPERTY_FILE: /config/mockserver.properties volumes: - ./tests/mockserver:/config ports: - "1080:1080"Observe: usamos portas separadas para os serviços de teste, para que não interfiram no desenvolvimento local.
2. Preparação do PHPUnit e inicialização do BD de teste
Configuração do phpunit.xml para testes de integração:
<phpunit bootstrap="tests/bootstrap.php"> <testsuites> <testsuite name="Integration"> <directory>tests/Integration</directory> </testsuite> </testsuites> <php> <env name="APP_ENV" value="test"/> <env name="KERNEL_CLASS" value="App\\Kernel"/> </php></phpunit>O arquivo tests/bootstrap.php é responsável por inicializar o esquema do BD e preencher com dados de teste:
require __DIR__ . '/../vendor/autoload.php';
// Cria o esquema do BD$pdo = new PDO('pgsql:host=db-test;port=5432;dbname=testdb', 'test', 'test');$pdo->exec(file_get_contents(__DIR__ . '/../migrations/schema.sql'));
// Carrega as fixturesrequire __DIR__ . '/Fixtures/LoadFixtures.php';Essa abordagem garante que cada execução de teste comece com um estado limpo e previsível.
3. Teste com APIs externas: MockServer e WireMock
Para simular serviços HTTP externos, usamos MockServer (ou WireMock). Criamos uma configuração de expectativas em um arquivo JSON:
// tests/mockserver/expectations/payment.json{ "httpRequest": { "method": "POST", "path": "/api/v1/charge" }, "httpResponse": { "statusCode": 200, "body": "{\\"status\\": \\"success\\", \\"transaction_id\\": \\"txn_123\\"}", "headers": { "Content-Type": "application/json" } }}No código PHP do teste, enviamos uma requisição para a URL real, que através da variável de ambiente aponta para o mock-server:
class PaymentIntegrationTest extends TestCase{ private PaymentService $paymentService;
protected function setUp(): void { $this->paymentService = new PaymentService( new HttpClient(['base_uri' => $_ENV['EXTERNAL_API_URL']])