Kotlin 与 Docker 集成测试:高级水平

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

Kotlin 与 Docker 集成测试:高级水平



集成测试是检查应用程序组件交互的关键阶段。在 Kotlin 和 Docker 生态系统中,由于容器化,这一过程达到了新的水平。在本文中,我们将探讨使用 Docker、Testcontainers 和 Kotlin DSL 进行集成测试配置和执行的高级技术。



1. 基础:使用 Kotlin DSL 的 Testcontainers

Testcontainers 是一个用于 Java/Kotlin 的库,用于管理测试中 Docker 容器的生命周期。Kotlin 提供了便捷的 DSL,简化了配置。



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


使用 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 // 在 DataSource 中使用 jdbcUrl println("Connected to: $jdbcUrl") }}


2. 并行运行容器

为了加速测试,可以并行运行容器。但需要注意端口冲突。使用动态端口并通过 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") }}


使用 Network 进行隔离,使用 waitingFor 等待容器就绪。



3. 测试中的 Docker Compose

对于复杂场景(数据库 + 消息代理 + 缓存),使用 DockerComposeContainer 非常方便。它加载 docker-compose.yml 并管理所有服务。



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

博客

书籍推荐