Testes em Sistemas Distribuídos

Integração e Testcontainers

Tutorial com Kafka e Redis reais em containers efêmeros para validar fluxo order.created.

Avançado 45 min 40 pontos Leitura 0%

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.py
  • services/order-service/tests/integration/conftest.py
  • services/payment-service/internal/tests/integration/payment_consumer_test.go
  • services/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 sleep fixo.
  • 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.