Testes de integração: as costuras onde os bugs moram
Os bugs de produção moram nas costuras: banco, APIs, filas. Testcontainers com dependências reais e efêmeras, fakes para terceiros e as regras da suíte rápida.
Os unitários provam que cada peça funciona sozinha. Mas os bugs de produção raramente moram dentro das peças: moram nas costuras: a query que o ORM gera diferente do esperado, o JSON que a API devolve com o campo noutro formato, a transação que não faz rollback, a mensagem que chega duplicada. Testes de integração existem para as costuras, o meio da pirâmide.
A regra de ouro: dependências reais, efêmeras
O erro histórico dos testes de integração era escolher entre dois males: mockar o banco (e não testar nada de real) ou apontar para um banco compartilhado (lento, sujo, flaky). A resposta moderna é subir a dependência de verdade, descartável, por suíte, e o padrão da indústria é o Testcontainers (testcontainers.com):
import { PostgreSqlContainer } from "@testcontainers/postgresql";
let container, db;
beforeAll(async () => {
container = await new PostgreSqlContainer("postgres:16").start();
db = criarConexao(container.getConnectionUri());
await rodarMigracoes(db); // as MESMAS migrações da produção
}, 60_000);
afterAll(async () => {
await container.stop(); // nasce limpo, morre sem rastro
});
it("persiste e recupera o pedido com itens", async () => {
const repo = new RepositorioDePedidos(db);
await repo.salvar(criarPedido({ itens: 3 }));
const salvo = await repo.buscarPorId("PED-1");
expect(salvo.itens).toHaveLength(3);
expect(salvo.total).toBe(540); // a query com join calculou certo?
});
Um Postgres real num container, com as migrações reais, testando a query real. É a diferença entre "o mock retornou o que mandei" e "o banco de verdade entende o que escrevi", exatamente onde o unitário não alcança.
As costuras que merecem teste
- Repositórios e queries: joins, transações (commit e rollback), constraints, os índices que você jurou que funcionam.
- A API por fora: com supertest (ou fetch no app subido), a requisição HTTP completa: rota, validação, status, contrato do JSON:
const res = await request(app)
.post("/pedidos")
.send({ clienteId: "CLI-1", itens: [...] })
.expect(201);
expect(res.body).toMatchObject({ status: "criado" });
- Filas e eventos: publica no broker de teste, consome, afirma o efeito (e a idempotência: a mesma mensagem duas vezes, efeito uma).
- Integrações de terceiros: aqui inverte: não teste contra a API real deles (lenta, instável, custa dinheiro). Um servidor fake local (nock, WireMock) simula os contratos, incluindo os erros: timeout, 500, resposta malformada, os cenários que o QA hostil pede.

As regras que mantêm a suíte rápida e confiável
- Isolamento por teste: cada teste cria seus dados (builders) e não depende dos vizinhos. Suíte que exige ordem de execução é castelo de cartas.
- Container por suíte, não por teste: subir o Postgres uma vez (segundos) e truncar tabelas entre testes (milissegundos). O equilíbrio entre isolamento e velocidade.
- Teste o rollback: todo mundo testa o caminho que dá certo; a transação que desfaz no erro é a que salva dados em produção.
- No CI desde o dia um: a esteira roda containers numa boa; integração que só roda "na máquina de quem lembra" não existe.
- Não re-teste a lógica: a regra de desconto já tem 20 unitários; a integração testa a persistência do pedido, não a matemática de novo. Cada camada com seu trabalho.
O sinal de maturidade
Times maduros têm uma proporção reveladora: dezenas de integrações cobrindo cada fronteira uma vez, não centenas repetindo lógica. Quando um teste de integração falha, a mensagem é precisa: "a costura X rasgou", sem arqueologia.
Montar essa camada (Testcontainers, builders, fakes de terceiros e o encaixe no CI) é parte da esteira de qualidade que construímos no serviço de Qualidade e Testes.
Sua camada de dados tem algum teste contra banco de verdade? Se a resposta é "só mock", a costura mais importante está no escuro. Fale com a IA da Rabelo Digital, aqui no canto da tela, e ela desenha o primeiro teste com Testcontainers para o seu stack. Sem formulário, sem espera.


Deixe um Comentário