Testes de Integração Kotlin com Docker: Nível Avançado

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Testes de Integração Kotlin com Docker: Nível Avançado



Testes de integração são uma etapa fundamental para verificar a interação entre os componentes de uma aplicação. No ecossistema Kotlin e Docker, esse processo atinge um novo nível graças à conteinerização. Neste artigo, abordaremos técnicas avançadas de configuração e execução de testes de integração usando Docker, Testcontainers e Kotlin DSL.



1. Fundamentos: Testcontainers com Kotlin DSL

Testcontainers é uma biblioteca para Java/Kotlin que gerencia o ciclo de vida de contêineres Docker dentro dos testes. Para Kotlin, há uma DSL conveniente que simplifica a configuração.



// build.gradle.ktsdependencies {    testImplementation("org.testcontainers:testcontainers:1.20.0")    testImplementation("org.testcontainers:postgresql:1.20.0")    testImplementation("org.jetbrains.kotlin:kotlin-test")}


Exemplo de teste com PostgreSQL:

import org.testcontainers.containers.PostgreSQLContainerimport org.testcontainers.junit.jupiter.Containerimport org.testcontainers.junit.jupiter.Testcontainersimport org.junit.jupiter.api.Test

@Testcontainersclass UserRepositoryTest {

companion object { @Container val postgres = PostgreSQLContainer<Nothing>("postgres:15-alpine") .withDatabaseName("testdb") .withUsername("test") .withPassword("test") }

@Test fun `should connect to database`() { val jdbcUrl = postgres.jdbcUrl // Usamos jdbcUrl no DataSource println("Connected to: $jdbcUrl") }}


2. Execução Paralela de Contêineres

Para acelerar os testes, é possível executar contêineres em paralelo. No entanto, é importante considerar conflitos de porta. Use portas dinâmicas e sincronização através de GenericContainer.



import org.testcontainers.containers.GenericContainerimport org.testcontainers.containers.Networkimport org.testcontainers.containers.wait.strategy.Waitimport java.time.Duration

class ParallelContainerTest {

companion object { private val network = Network.newNetwork()

private val redis1 = GenericContainer<Nothing>("redis:7-alpine") .withNetwork(network) .withNetworkAliases("redis1") .withExposedPorts(6379) .waitingFor(Wait.forListeningPort())

private val redis2 = GenericContainer<Nothing>("redis:7-alpine") .withNetwork(network) .withNetworkAliases("redis2") .withExposedPorts(6379) .waitingFor(Wait.forListeningPort())

init { redis1.start() redis2.start() } }

@Test fun `parallel containers test`() { val port1 = redis1.getMappedPort(6379) val port2 = redis2.getMappedPort(6379) println("Redis1 port: $port1, Redis2 port: $port2") }}


Use Network para isolamento e waitingFor para aguardar a prontidão do contêiner.



3. Docker Compose em Testes

Para cenários complexos (banco de dados + broker de mensagens + cache), é conveniente usar DockerComposeContainer. Ele carrega o docker-compose.yml e gerencia todos os serviços.



import org.testcontainers.containers.DockerComposeContainerimport java.io.File

class FullStackTest {

companion object { private val compose = DockerComposeContainer<Nothing>( File("src/test/resources/docker-compose.yml") ).apply { withExposedService("postgres_1", 5432) withExposedService("redis_1", 6379) withLocalCompose(true) start() } }

@Test fun `full integration test`() { val pgPort = compose.getServicePort("postgres_1", 5432) val redisPort = compose.getServicePort

Blogs

Book Recommendations