Acesse o painel da sua conta

Não tem uma conta? Registrar

Entrar em contato

Visite também nosso site craftxp.com.br

  • img
  • img
  • img
  • img
  • img
  • img

Entre em contato

Testcontainers na Prática: Testes de Integração com Docker para Microsserviços Modernos

Testcontainers na Prática: Testes de Integração com Docker para Microsserviços Modernos

Por que Testes de Integração Ainda São um Desafio?

Mocks e bancos em memória são soluções tradicionais para testes de integração, mas trazem uma fragilidade silenciosa: o comportamento do H2 não é idêntico ao do PostgreSQL, um mock de Redis não valida comandos reais, e um Fake S3 não reproduz as nuances de latência e consistência do serviço real. Bugs que passam nesses ambientes artificiais frequentemente explodem em produção.

O Testcontainers resolve esse problema de forma elegante: ele gerencia containers Docker reais dentro do ciclo de vida dos seus testes. Cada execução ganha um ambiente isolado, idêntico ao de produção, que é destruído automaticamente ao final.

Como o Testcontainers Funciona

Disponível para Java, Python, Go, Node.js e outras linguagens, o Testcontainers utiliza a API do Docker para:

  • Criar containers a partir de imagens Docker reais (postgres:16-alpine, redis:7, confluentinc/cp-kafka)
  • Configurar variáveis de ambiente, volumes, redes e portas dinâmicas
  • Executar scripts de inicialização (SQL de schema, seed data) antes dos testes
  • Aguardar prontidão com health checks customizados
  • Destruir tudo ao final dos testes — sem resíduos, sem estado compartilhado

Exemplo com Java, Spring Boot e PostgreSQL

@SpringBootTest
@Testcontainers
class UsuarioRepositoryTest {

    @Container
    static PostgreSQLContainer<?> postgres =
        new PostgreSQLContainer<>("postgres:16-alpine")
            .withDatabaseName("testdb")
            .withUsername("test")
            .withPassword("test");

    @DynamicPropertySource
    static void properties(DynamicPropertyRegistry r) {
        r.add("spring.datasource.url", postgres::getJdbcUrl);
        r.add("spring.datasource.username", postgres::getUsername);
        r.add("spring.datasource.password", postgres::getPassword);
    }

    @Autowired
    UsuarioRepository repository;

    @Test
    void buscaPorEmail() {
        repository.save(new Usuario("Maria", "maria@email.com"));
        var result = repository.findByEmail("maria@email.com");
        assertThat(result).isPresent();
        assertThat(result.get().getNome()).isEqualTo("Maria");
    }
}

Anotações-chave: @Testcontainers gerencia o ciclo de vida, @Container declara o container PostgreSQL, e @DynamicPropertySource injeta as credenciais dinâmicas no Spring. Quando o teste termina, o container é removido automaticamente pelo Ryuk.

Exemplo com Python, Redis e Testcontainers

from testcontainers.redis import RedisContainer
import redis

def test_cache_com_redis_real():
    with RedisContainer("redis:7-alpine") as redis_container:
        host = redis_container.get_container_host_ip()
        port = redis_container.get_exposed_port(6379)
        client = redis.Redis(host=host, port=port)

        client.set("sessao:123", "ativo")
        assert client.get("sessao:123") == b"ativo"
        # Container é destruído ao sair do 'with'

Módulos que Valem Ouro

  • LocalStack: emula S3, SQS, DynamoDB, Lambda — essencial para testar integrações AWS localmente
  • Kafka / Redpanda: validade producer/consumer sem cluster externo
  • Toxiproxy: simula latência e falhas de rede para testar resiliência
  • MongoDB: teste agregações complexas com o banco real, não com o em-memory
  • Elasticsearch: valide mappings e queries de busca full-text

Boas Práticas em Produção

  1. Prefira Alpine: imagens -alpine reduzem download e footprint — cruciais em CI paralelo
  2. Portas dinâmicas sempre: evite conflitos entre execuções concorrentes
  3. Compartilhe com cuidado: containers podem ser compartilhados dentro da mesma classe via static, nunca entre classes sem limpeza
  4. Pré-baixe imagens no CI: acrescente docker pull no setup do pipeline para evitar timeouts
  5. Não desabilite o Ryuk: o container Ryuk garante limpeza mesmo se os testes forem abruptamente interrompidos

Testcontainers em Pipelines CI/CD

No GitHub Actions, GitLab CI ou CircleCI, o Docker já está disponível. Configure o serviço Docker e os testes rodam sem modificações:

# .github/workflows/ci.yml
jobs:
  test:
    runs-on: ubuntu-latest
    services:
      docker:
        image: docker:27-dind
        options: --privileged
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-java@v4
        with:
          java-version: '21'
      - run: ./mvnw test
      # Testcontainers gerencia tudo automaticamente

Conclusão

Testcontainers eleva a confiabilidade dos testes de integração ao eliminar o abismo entre o ambiente de teste e o de produção. Com containers reais, descartáveis e programáticos, você ganha testes mais rápidos de escrever, mais confiáveis na execução e que pegam bugs que mocks jamais pegariam. Adote em um módulo hoje e sinta a diferença.

Craft XP
Craft XP