Testcontainers e uma biblioteca que sobe containers Docker dentro dos seus testes de integracao. Em vez de mockar o banco de dados, voce usa um banco de verdade que nasce e morre com o teste.
Adicione a dependencia no build.gradle.kts:
testImplementation("org.testcontainers:testcontainers:1.20.0")
testImplementation("org.testcontainers:postgresql:1.20.0")
testImplementation("org.testcontainers:junit-jupiter:1.20.0")
O teste mais simples com PostgreSQL:
@Testcontainers
@SpringBootTest
class UsuarioRepositoryTest {
companion object {
@Container
val postgres = PostgreSQLContainer<Nothing>("postgres:16").apply {
withDatabaseName("testdb")
withUsername("test")
withPassword("test")
}
}
@Autowired
lateinit var repo: UsuarioRepository
@Test
fun deveSalvarUsuario() {
val usuario = Usuario(nome = "Joao", email = "joao@email.com")
val salvo = repo.save(usuario)
assertThat(salvo.id).isNotNull()
}
}
O Testcontainers sobe um container PostgreSQL antes dos testes e derruba depois. Nao precisa de banco instalado na maquina.
Para configurar o Spring Boot automaticamente:
@DynamicPropertySource
fun configurarProps(registry: DynamicPropertyRegistry) {
registry.add("spring.datasource.url", postgres::getJdbcUrl)
registry.add("spring.datasource.username", postgres::getUsername)
registry.add("spring.datasource.password", postgres::getPassword)
}
Isso substitui as properties do application.properties pela URL do container que acabou de subir.
Para Redis:
@Container
val redis = GenericContainer<Nothing>("redis:7").apply {
withExposedPorts(6379)
}
@DynamicPropertySource
fun redisProps(registry: DynamicPropertyRegistry) {
registry.add("spring.redis.host", redis::getHost)
registry.add("spring.redis.port") { redis.getMappedPort(6379).toString() }
}
Testcontainers tambem suporta Kafka:
@Container
val kafka = KafkaContainer(DockerImageName.parse("confluentinc/cp-kafka:7.6.0"))
@DynamicPropertySource
fun kafkaProps(registry: DynamicPropertyRegistry) {
registry.add("spring.kafka.bootstrap-servers", kafka::getBootstrapServers)
}
Para reaproveitar o container entre varios testes:
@Testcontainers
abstract class AbstractIntegrationTest {
companion object {
@Container
val postgres = PostgreSQLContainer<Nothing>("postgres:16").apply {
withDatabaseName("testdb")
withUsername("test")
withPassword("test")
start()
}
@DynamicPropertySource
@JvmStatic
fun props(registry: DynamicPropertyRegistry) {
registry.add("spring.datasource.url", postgres::getJdbcUrl)
registry.add("spring.datasource.username", postgres::getUsername)
registry.add("spring.datasource.password", postgres::getPassword)
}
}
}
Agora toda classe que estender AbstractIntegrationTest ganha um banco PostgreSQL real.
Dica: se os testes ficarem lentos, use withReuse(true) no container. Isso mantem o container vivo entre execucoes. So nao esqueca de configurar testcontainers.reuse.enable=true em ~/.testcontainers.properties.
That's all for now.
Thanks for reading!
Top comments (0)