Testes em Sistemas Distribuídos
Integração e Testcontainers
Tutorial com Kafka e Redis reais em containers efêmeros para validar fluxo order.created.
Nesta aula você vai
- Subir dependências reais de integração com Testcontainers
- Validar publicação e consumo de eventos Kafka ponta a ponta
- Padronizar comandos de integração para execução local e CI
Integração e Testcontainers
Nesta aula você vai testar integração real entre order-service e payment-service usando Kafka e Redis em containers temporários.
Arquivos usados
services/order-service/tests/integration/test_order_created_event.pyservices/order-service/tests/integration/conftest.pyservices/payment-service/internal/tests/integration/payment_consumer_test.goservices/customer-service/src/test/java/com/amo/customer/integration/CustomerKafkaIT.java
Passo 1 - Dependências de teste
Python (order-service):
pytest==8.3.2
testcontainers[kafka]==4.8.0
redis==5.0.8
Java (customer-service):
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>kafka</artifactId>
<scope>test</scope>
</dependency>
Go (payment-service):
go get github.com/testcontainers/testcontainers-go
go get github.com/testcontainers/testcontainers-go/modules/kafka
Passo 2 - Fixture de Kafka com Testcontainers (Python)
services/order-service/tests/integration/conftest.py:
@pytest.fixture(scope="session")
def kafka_bootstrap():
with KafkaContainer("confluentinc/cp-kafka:7.6.1") as kafka:
yield kafka.get_bootstrap_server()
Passo 3 - Teste de integração do evento order.created
test_order_created_event.py:
def test_publish_order_created_event(client, kafka_consumer, db_session):
payload = {"customerId": "c-100", "items": [{"sku": "book-1", "qty": 1}]}
response = client.post("/orders", json=payload)
assert response.status_code == 201
event = kafka_consumer.poll(timeout=10.0)
assert event["eventType"] == "order.created"
Passo 4 - Teste de consumo no Payment (Go)
payment_consumer_test.go:
func TestConsumeOrderCreated_StoresPendingPayment(t *testing.T) {
env := integration.NewKafkaEnv(t)
consumer := consumers.NewPaymentConsumer(env.Brokers, env.DB)
env.Publish("order.created", fixtures.OrderCreatedPayload("ord-1"))
require.Eventually(t, func() bool {
return env.DB.HasPayment("ord-1", "PENDING")
}, 8*time.Second, 300*time.Millisecond)
}
Comandos de execução
cd services/order-service && pytest tests/integration -q
cd services/payment-service && go test ./internal/tests/integration/... -v
cd services/customer-service && ./mvnw -q test -Dtest=*IT
make test-integration
Boas práticas anti-flaky
- Use polling com timeout ao invés de
sleepfixo. - Gere tópicos com sufixo único por teste.
- Limpe estado do banco no setup/teardown.
- Defina timeout maior para CI.
Resumo
Você implementou testes de integração com infraestrutura real, reduzindo diferenças entre local e CI e aumentando confiança no fluxo assíncrono.