Módulo 6 · Engenharia de Software · ES06 · Aula 8 de 10
Testes de Integração
em arquiteturas SOA
Black-box · Testcontainers · VCR / WireMock.Net · Ponderada individual
🧪 O que é integração
⬛ Testes black-box
🐳 Testcontainers
📼 VCR / WireMock
🔀 Merge Request
DAILY · 15 MIN
15:00
🐛 1 bug que escapou de teste unitário
🔌 1 dependência externa do MVP (API do parceiro / serviço outro squad)
❓ 1 dúvida sobre Testcontainers ou VCR
🤝 Preciso de ajuda?
Cada aluno em 1 minuto · começamos em ordem alfabética
Autoestudos · Pré-aula 📚
3 tarefas individuais para chegar pronto + leituras sugeridas

📚 Leituras sugeridas

📌 Material de chegada: 1 dependência possuída (BD/broker do projeto) + 1 dependência consumida (API externa) + 1 dúvida concreta. Esses 3 itens alimentam o daily de abertura.

Agenda da Aula
2 horas · 30 min teoria + 90 min ponderada individual
⏱️ 30 min
EXPOSIÇÃO

🧪 Integração + Black-box + Testcontainers + VCR

Pirâmide, contrato como observável, mapa SOA (possuído × consumido), código .NET para Testcontainers e WireMock.Net.

  • O que é integração + pirâmide (slides 5–6)
  • Black-box + mapa SOA (slides 8–9)
  • Testcontainers + VCR (slides 10–13)
  • Mapa decisório + ⚠️ VCR ≠ contract (14–15)
⏱️ 90 min
PONDERADA · INDIVIDUAL

🔀 Atividade — Merge Request

Implementar 1 teste de integração no projeto: 1 dependência possuída (Testcontainers) ou consumida (WireMock). Entrega via MR com RF + RNF.

  • 1 cenário de sucesso + 1 cenário de erro
  • Justificar Testcontainers ou VCR
  • Rastrear RF + eixo ISO 25010
  • MR + pipeline verde

🎯 Saída do dia: link do Merge Request postado na plataforma da disciplina. Vale nota ponderada — fechar antes do fim dos 90 min.

O que é Teste de Integração? 🧪
Quando duas ou mais peças conversam · contraste com unitário e E2E
Teste de integração exercita dois ou mais componentes do sistema conversando entre si — controller↔service↔repository, app↔banco, app↔serviço externo — para validar que o wiring funciona, não apenas a lógica isolada. — Definição operacional adotada no módulo

🟢 Unit · isolado

1 classe, 0 dependências reais. Mocks substituem tudo. Roda em milissegundos.

Pergunta: "Esta peça faz o que prometeu?"

🟡 Integração · combinado

Várias peças + dependências reais ou semi-reais (BD em container, HTTP em cassete). Roda em segundos.

Pergunta: "Estas peças combinam direito?"

🔴 E2E · sistema inteiro

Tudo de pé, navegador real, ambiente real. Mede o caminho do usuário. Minutos por suite.

Pergunta: "O usuário consegue chegar lá?"

📌 Foco do dia: a faixa amarela. Em SOA, é onde mais aparecem bugs caros — e onde Testcontainers + VCR brilham.

A Pirâmide de Testes 🧪
Base larga e barata · topo estreito e caro · integração no meio
E2E
poucos · frágeis · lentos
End-to-Endnavegador real · ambiente real · minutos por suite
Integração
dezenas · médios · ⚠️ aula de hoje
Integraçãoapp em-process · BD real ou fake · segundos
Unitário
centenas · baratos · rápidos
Unitáriouma classe isolada · mocks · milissegundos

🟢 Base · Unit Tests

Centenas de testes rodando em milissegundos. Garantem que cada peça funciona isolada. Falhas de unit tests não pegam wiring.

🟡 Meio · Integration Tests

Dezenas, não centenas. Sobem a aplicação de verdade para validar wiring entre camadas e dependências. Foco do dia.

🔴 Topo · End-to-End

Poucos casos críticos de fluxo (login → checkout). Caros de manter, frágeis a mudanças de UI. Não substituem integração.

Por que Testes de Integração? 🔌
O que o teste unitário sozinho NÃO consegue capturar

🔗 Wiring entre camadas

Controller chama Service que chama Repository. Cada peça passa nos seus unit tests, mas a injeção de dependência ou o middleware podem estar quebrados.

🗃️ Contratos com o BD real

EF Core gera SQL diferente de mocks. Migrations, índices, tipos NUMERIC × DECIMAL: tudo só aparece quando você roda contra um banco de verdade.

🔐 Auth, cache, middleware

JWT, claims, políticas de autorização, headers de cache. Tudo isso só executa quando o pipeline HTTP roda inteiro — algo que unit tests pulam.

🌐 Integração com serviço externo

Em SOA, sua app chama a API de outro squad. Headers, timeouts, retries, contratos de payload — só aparecem em integração, nunca em mocks isolados.

1 bug de integração custa 10× o que custa um bug unitário — porque ele só aparece quando várias camadas conversam, e isolar a causa exige rodar tudo junto. — Princípio de custo de defeito · adaptado de Boehm e do "shift left"
Teste Black-box · Contrato como Observável ⬛
Testar o que entra e o que sai — sem olhar para dentro

⬛ Black-box

Você só conhece o contrato: entrada (request, headers, payload) → saída (status, body, side effects). Implementação interna é irrelevante.

Vantagem: o teste sobrevive a refactor. Mude o ORM, troque o algoritmo, reescreva a service — se o contrato continua igual, o teste continua verde.

⬜ White-box (para contrastar)

Testa caminhos internos: cobertura de linhas, branches, métodos privados. Bom para unit. Em integração SOA quebra a cada refactor e acopla teste à implementação.

🎯 O contrato em SOA

Em arquitetura orientada a serviços, o contrato é o que o outro squad consegue ver: o endpoint HTTP, o schema do payload, o status code, o header. É a sua superfície pública.

✅ Black-box = teste de contrato

Quando você testa POST /pedidos só pela request/response, você está protegendo o contrato — exatamente o que outro serviço SOA consome. É o ângulo certo para integração.

📌 Regra de ouro: em teste de integração, não inspecione estado interno. Se você precisar abrir o objeto pra checar um campo privado, refatore o teste — não a regra.

SOA · Mapa de Dependências 🗺️
O que você possui sobe em container · o que você consome grava em cassete

🏠 Dependências POSSUÍDAS

São suas. Você controla schema, deploy, versão. Você pode subir uma cópia idêntica em qualquer máquina.

  • BD do seu serviço (PostgreSQL, SQL Server)
  • Cache do seu serviço (Redis local)
  • Message broker que você gerencia (RabbitMQ)
  • Storage que você administra (MinIO/S3 local)
🐳 Ferramenta: Testcontainers
2 caminhos
distintos

🌐 Dependências CONSUMIDAS

São de outro squad (ou de terceiros). Você só conhece pela API HTTP. Não controla o deploy nem o uptime.

  • API REST do squad de pagamentos
  • Serviço de catálogo do parceiro
  • Provider de autenticação (Auth0, Cognito)
  • Gateway de email/SMS (SendGrid, Twilio)
📼 Ferramenta: VCR / WireMock.Net
Em SOA, a primeira pergunta a fazer sobre cada dependência é: "eu possuo ou eu consumo?" A resposta define a ferramenta de teste. — Princípio orientador da aula
🐳 Testcontainers · Conceito
Sobe a dependência REAL em container Docker, durante o teste

🐳 O que é

Biblioteca que sobe containers Docker descartáveis dentro do ciclo de vida do teste. PostgreSQL real, Redis real, RabbitMQ real — não um mock, não um in-memory.

🎯 Quando usar

Sempre que o dialeto real importa: JSONB do Postgres, full-text search, índice GIN, transações isoladas, particionamento. SQLite InMemory não fala esses dialetos.

⚡ Trade-offs

Custo: 3–10s de startup por container. Mais lento que mock.

Benefício: fidelidade total ao prod. Bug que aparece aqui, aparece lá.

🔧 Pré-requisito

Docker rodando na máquina (local) e no runner do CI. Sem Docker, sem Testcontainers — verifique antes de adotar no projeto.

📌 Mental model: Testcontainers transforma a frase "rodei contra Postgres real" em algo que cabe num dotnet test determinístico, sem precisar de banco compartilhado.

🐳 Testcontainers · Código .NET
Fixture com PostgreSqlBuilder + IAsyncLifetime · sobe e derruba por suite

🔄 IAsyncLifetime

xUnit chama InitializeAsync antes da suite e DisposeAsync ao final. Sem isso, container vaza.

🧪 IClassFixture

Compartilha o mesmo container entre todos os testes da classe — startup uma vez só, isolamento por transação.

🧹 Isolamento

Combine com Respawn ou TRUNCATE em Setup de cada teste pra garantir banco limpo.

📼 VCR · Record & Replay HTTP
Grava UMA vez a interação real · reproduz determinístico para SEMPRE

📼 O conceito do cassete

Nome veio do VCR.py (Ruby/Python). Você roda o teste 1 vez contra a API real, ele grava request + response num arquivo (o cassete). Próximas execuções: o HTTP é interceptado e a resposta vem do cassete.

🎯 Quando usar

Dependências que você NÃO possui: API REST de outro squad, gateway de pagamento, provider de autenticação. Qualquer HTTP fora do seu controle.

✅ O que ele resolve

  • Pipeline determinístico — sem flakiness de rede
  • Sem depender de uptime do provider
  • Documenta executável "o que eu esperava"
  • CI pode rodar offline

🛠️ No .NET

A biblioteca padrão de mercado é WireMock.Net. Suporta stub manual + modo recording proxy: você define a URL real, ele grava o roundtrip, depois replay-only.

📌 Mental model: cassete = "foto do contrato que o outro serviço me deu naquele dia". É frozen-in-time. Útil, mas com cuidado — voltaremos a esse ponto.

📼 WireMock.Net · Código .NET
Stub HTTP estável · pode gravar uma vez e reproduzir sempre

📼 Modo gravação

WithProxy("https://api.real/") + SaveMapping() grava o roundtrip em JSON. Próximas execuções: replay only.

🔒 Pipeline offline

Cassete versionado no repo (Mappings/*.json). CI nunca chama a API real — determinístico e rápido.

🎚️ Cenário de erro

Crie 2 mappings: um pro 200 (sucesso) e outro pro 503/timeout (erro). Teste o comportamento em cada caso.

🗺️ Container ou Cassete? · Mapa Decisório
A pergunta certa para cada dependência
Pergunta🐳 Testcontainers📼 VCR / WireMock.Net
Quem possui?você Schema, deploy, versão.outro squad ou terceiro Você só consome via HTTP.
Exemplos típicosPostgreSQL, Redis, RabbitMQ, MinIO — do seu serviço.API de pagamentos, catálogo de outro squad, Auth0, SendGrid.
O que está rodando?O processo real em container Docker.Um stub HTTP que devolve respostas pré-gravadas.
Custo de execução3–10s de startup por container.Milissegundos. Quase grátis.
Pega bug de dialeto?SIM JSONB, full-text, transações reais.não Você gravou o que o provider devolveu, nada mais.
Pega quebra do provider?N/A · o provider é você.não Se o provider mudar, seu cassete continua verde — falsamente.
Cobre cenários de falha?Sim — derrube o container e veja o comportamento.Sim — crie mapping de 503/timeout/payload inválido.

📌 Regra prática: em SOA, mapeie as dependências do seu serviço em 2 colunas — possuídas e consumidas — antes de escrever o primeiro teste de integração. A ferramenta sai do mapa.

⚠️ Cuidado · VCR NÃO é Contract Testing
A confusão mais cara em SOA — entenda antes de vender errado

📼 O que o cassete faz bem

Isolar seu teste de integração da dependência externa. Pipeline determinístico, sem flakiness, documentação executável do que você esperava.

❌ O que ele NÃO faz

  • Cassete envelhece em silêncio — provider muda, teste continua verde testando o passado.
  • Provider nunca é verificado — o squad do outro lado nem sabe que cassete existe.
  • Sem broker compartilhado — vive só no seu repo.
  • Sem verificação bidirecional — só você sabe se quebrou.

🤝 Contract testing DE VERDADE

Pact é o canônico em SOA: o consumer define o contrato esperado, o provider executa esses contratos no próprio build dele. Quebrou no provider? Build falha no provider.

Alternativas: Spring Cloud Contract, OpenAPI schema validation com Schemathesis.

🎯 Como vender certo

"Usei WireMock pra isolar a dependência externa em teste de integração. Para contrato de verdade, a stack é Pact." — Essa é a frase que passa em entrevista técnica.

VCR resolve isolamento de dependência consumida em teste de integração. Não resolve contrato. Os dois problemas são diferentes — e ferramentas diferentes. — Princípio honesto da aula
📓
Atividade Ponderada
Individual
90 minutos · 1 fluxo da API .NET · Testcontainers + VCR obrigatórios · fluxo único por aluno no grupo · entrega via Merge Request com RF + RNF
🧪 1 sucesso + 1 erro
🐳 Testcontainers (possuída)
📼 WireMock.Net / VCR (consumida)
🤝 Fluxo único no grupo
📋 RF + RNF (ISO 25010)
Atividade Ponderada · Descrição 📋
Pergunta-base · escopo · entrega
Individualmente, implemente 1 teste de integração de um fluxo da API .NET que toque uma dependência possuída (testada com Testcontainers) e uma dependência consumida (testada com WireMock.Net / VCR). Antes de codar, registre seu fluxo na tabela de coordenação do grupo — fluxos duplicados entre alunos do mesmo grupo são inválidos. Entrega via Merge Request com RF + RNF. — Pergunta-base · Aula 8 · Ponderada Individual
TEMA
🎯

1 fluxo · 2 ferramentas obrigatórias

Fluxo que toque possuída (BD/broker) e consumida (API externa). Setup obrigatório com Testcontainers + WireMock.Net em xUnit.

COORDENAÇÃO
🤝

Fluxo único por aluno no grupo

Antes de codar, registre o fluxo numa tabela no README (aluno · fluxo · link do MR). Sem duplicar fluxo entre colegas — força distribuição.

ENTREGA
⏱️

90 min · MR + link na plataforma

Branch test/integration-{flow}, dotnet test verde no pipeline, MR com RF + RNF, link direto na plataforma da disciplina.

🧠 Assuntos relacionados: Qualidade de software · Testes de integração · Arquitetura SOA · ISO/IEC 25010.

📚 Conteúdos relacionados: Testes black-box · Testcontainers · WireMock.Net · Merge Request workflow.

Atividade · 5 Critérios de Entrega 📐
Os 5 critérios são obrigatórios · ⭐ Excelência é bônus que diferencia a nota · total 10 pts
01
🤝
1,0 pt

Coordenação no grupo

Fluxo único registrado em tabela no README do repo (aluno · fluxo · link MR).

Sem duplicar entre colegas do grupo.

02
🧪
3,0 pts

Testes com TC + VCR

xUnit + Testcontainers (possuída) + WireMock.Net (consumida). 1 sucesso + 1 erro.

dotnet test verde.

03
🔀
1,5 pt

Merge Request

MR no repo oficial do grupo (Open ou Merged).

Branch test/integration-{flow}.

04
📋
2,0 pts

Regra de Negócio (RF)

Descrição do MR cita qual RF o teste valida.

RF exato + falha crítica.

05
🎚️
2,5 pts

RNF (ISO 25010)

Eixo: eficiência, segurança, confiabilidade, manutenibilidade.

RNF exato (ex.: "RNF02").

📌 Fluxo de entrega (individual):

  1. Coordenar: escolher fluxo único + registrar na tabela do README do grupo
  2. Mapear: identificar dependência possuída (BD/broker) e consumida (API externa) do fluxo
  3. Branch test/integration-{flow} · setup com Testcontainers + WireMock.Net
  4. Escrever 1 cenário de sucesso + 1 cenário de erro · garantir dotnet test verde
  5. Abrir MR · descrição com classificação das dependências + RF + RNF
  6. Postar o link do MR na plataforma da disciplina
🛠️
Mão na massa · Atividade Ponderada
90 minutos para entregar o MR com os 5 critérios — coordenação, testes (TC + VCR), MR, RF, RNF. Cada minuto conta.
1️⃣ 🤝 Coordenar no grupo · registrar fluxo único no README
2️⃣ Identificar dependências do fluxo (possuída + consumida)
3️⃣ Branch test/integration-{flow}
4️⃣ 🐳 Setup Testcontainers (BD/broker)
5️⃣ 📼 Setup WireMock.Net (API externa)
6️⃣ Escrever teste de sucesso (black-box)
7️⃣ Escrever teste de erro/exceção
8️⃣ Garantir dotnet test verde
9️⃣ MR com classificação + RF + RNF ⭐
🔟 Postar link na plataforma
💡 Estratégia: comece pela coordenação (pega fluxo bom antes dos colegas), depois TC + VCR + asserts. Por último, refine a descrição do MR para os ⭐ Excelência.
🎯
A aula 8 me ensinou que...
Em SOA, a primeira pergunta é "eu possuo ou eu consumo?". A resposta define se vou subir um container ou gravar um cassete. Na aula 9 levamos isso para a nuvem: os testes de hoje viram smoke tests pós-deploy.
✅ O que é integração
✅ Pirâmide de testes
✅ Por que integração
✅ Black-box · contrato
✅ SOA · possuídas × consumidas
✅ Testcontainers
✅ VCR / WireMock.Net
✅ ⚠️ VCR ≠ contract
✅ MR como entrega
✅ Ponte para SOA na nuvem · aula 9
Módulo 6 · Engenharia de Software · Aula 8 de 10