Teste de Integração Java com Docker: Nível Avançado
\nO teste de integração é uma etapa chave no desenvolvimento de aplicações Java modernas, especialmente em arquiteturas de microsserviços. O uso do Docker permite isolar ambientes de teste, garantindo reprodutibilidade e independência de serviços externos. Neste artigo, abordaremos técnicas avançadas de teste de integração de aplicações Java com Docker, incluindo o trabalho com a biblioteca Testcontainers, configuração de contêineres personalizados, teste de cenários assíncronos e integração em pipelines CI/CD. O material é voltado para desenvolvedores já familiarizados com os fundamentos do JUnit e Docker.
\n\nPor que o Docker é crítico para o teste de integração Java?
\nO teste de integração tradicional frequentemente enfrenta problemas: bancos de dados de teste instáveis, conflitos de porta, configuração manual do ambiente. O Docker resolve esses problemas fornecendo contêineres leves e efêmeros. Cada teste pode iniciar seu próprio banco de dados, broker de mensagens ou cache e, após a conclusão, destruí-los automaticamente. Isso torna os testes:
\n- \n
- Isolados: cada cenário de teste funciona em um ambiente limpo. \n
- Reprodutíveis: comportamento idêntico na máquina local e no CI. \n
- Paralelos: contêineres não entram em conflito por portas graças ao mapeamento dinâmico. \n
Para Java, a biblioteca mais popular é o Testcontainers, que fornece uma API simples para gerenciar contêineres a partir dos testes.
\n\nConfiguração do Testcontainers: do simples ao complexo
\nVamos começar com um exemplo básico — teste da camada DAO com PostgreSQL. Adicione a dependência no pom.xml:
<dependency>\n <groupId>org.testcontainers</groupId>\n <artifactId>testcontainers</artifactId>\n <version>1.19.3</version>\n <scope>test</scope>\n</dependency>\n<dependency>\n <groupId>org.testcontainers</groupId>\n <artifactId>postgresql</artifactId>\n <version>1.19.3</version>\n <scope>test</scope>\n</dependency>\nAgora, vamos criar um teste que utiliza o contêiner PostgreSQL:
\nimport org.junit.jupiter.api.Test;\nimport org.testcontainers.containers.PostgreSQLContainer;\nimport org.testcontainers.junit.jupiter.Container;\nimport org.testcontainers.junit.jupiter.Testcontainers;\nimport java.sql.Connection;\nimport java.sql.DriverManager;\nimport java.sql.ResultSet;\nimport static org.junit.jupiter.api.Assertions.assertEquals;\n\n@Testcontainers\npublic class UserRepositoryIntegrationTest {\n\n @Container\n private PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>("postgres:15")\n .withDatabaseName("testdb")\n .withUsername("test")\n .withPassword("test");\n\n @Test\n void shouldSaveAndFindUser() throws Exception {\n // Obtém a URL dinâmica do contêiner\n String jdbcUrl = postgres.getJdbcUrl();\n String username = postgres.getUsername();\n String password = postgres.getPassword();\n\n try (Connection conn = DriverManager.getConnection(jdbcUrl, username, password)) {\n conn.createStatement().execute("CREATE TABLE IF NOT EXISTS users (id SERIAL PRIMARY KEY, name VARCHAR(255))");\n conn.createStatement().execute("INSERT INTO users (name) VALUES ('Alice')");\n ResultSet rs = conn.createStatement().executeQuery("SELECT name FROM users WHERE id = 1");\n rs.next();\n assertEquals("Alice", rs.getString("name"));\n }\n }\n}\nO Testcontainers inicia automaticamente o contêiner antes dos testes e o interrompe após. Para nível avançado, use contêineres personalizados (por exemplo, com dados pré-carregados