Testes em PHP: Unit, Integration, E2E em nível avançado

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Testes em PHP: Unit, Integration, E2E em nível avançado



No desenvolvimento web moderno em PHP, a qualidade do código deixou de ser uma opção — é uma condição obrigatória para a sobrevivência do projeto. Testes unitários básicos são familiares a todo desenvolvedor, mas assim que o projeto ultrapassa os limites do "Hello World", surge a necessidade de abordagens mais complexas: testes de integração, verificação da interação entre componentes e testes ponta a ponta (E2E) de cenários de usuário.



Este artigo é destinado a desenvolvedores PHP de nível Middle e superior, que já conhecem o PHPUnit e desejam aprofundar seus conhecimentos. Abordaremos técnicas avançadas: testes com dependências externas, trabalho com contêineres de teste, isolamento de infraestrutura e construção de uma estratégia de testes completa.



1. Testes Unitários Avançados: Objetos Mock e Stubs



Em nível avançado, os testes unitários deixam de ser apenas a verificação de funções matemáticas. Eles testam a lógica de negócios, isolada do mundo externo. As ferramentas-chave são Mock e Stub.



Stub retorna dados predefinidos. Mock verifica como exatamente os métodos foram chamados (número de chamadas, ordem dos argumentos).



Vamos considerar um exemplo: um serviço de pagamento que envia uma requisição para um gateway de pagamento.



<?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; }}

// Teste usando PHPUnitclass PaymentServiceTest extends TestCase { public function testSuccessfulPaymentLogsInfo(): void { // Criando um Stub para o gateway $gatewayStub = $this->createStub(PaymentGatewayInterface::class); $gatewayStub->method('charge') ->willReturn(new PaymentResult(true));

// Criando um Mock para o logger (verificando a chamada) $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 avançada: use willReturnCallback() para respostas dinâmicas e withConsecutive() para verificar a sequência de chamadas.



2. Testes de Integração: Banco de Dados e APIs Externas



Os testes de integração verificam como seu código interage com componentes reais: banco de dados, sistema de arquivos, cache. Aqui não se pode confiar em mocks — é necessária uma infraestrutura real.



Problema: os testes se tornam lentos e frágeis. Solução: usar contêineres de teste (Testcontainers) ou bancos de dados SQLite embutidos.



Exemplo de teste de integração para um repositório de usuários com 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