1. 概述

本文将介绍 Testcontainers 的 JDBC 支持功能,并对比两种在测试中启动 Docker 容器的方式:

  1. 手动管理容器生命周期:通过代码直接控制容器启动/停止
  2. JDBC 驱动自动管理:通过配置属性自动启动容器

我们将从手动管理开始,逐步展示如何通过 JDBC 支持简化配置。

2. 手动管理容器生命周期

Testcontainers 是一个轻量级测试框架,提供可销毁的 Docker 容器。使用它可以:

避免使用 Mock
测试真实服务(数据库、消息队列等)
消除外部依赖

2.1 基础配置

以 PostgreSQL 测试为例,首先添加依赖:

<dependency>
    <groupId>org.testcontainers</groupId>
    <artifactId>testcontainers</artifactId>
    <version>1.19.8</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.testcontainers</groupId>
    <artifactId>postgresql</artifactId>
    <version>1.19.8</version>
    <scope>test</scope>
</dependency>

2.2 容器生命周期管理

手动管理需要完成四个步骤:

  1. 创建容器对象
  2. 测试前启动容器
  3. 配置应用连接参数
  4. 测试后销毁容器

使用 JUnit5 和 Spring Boot 实现:

@SpringBootTest
class FullTestcontainersLifecycleLiveTest {
    static PostgreSQLContainer postgres = new PostgreSQLContainer("postgres:16-alpine")
      .withDatabaseName("test-db");

    @BeforeAll
    static void beforeAll() {
        postgres.start();
    }

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

    @AfterAll
    static void afterAll() {
        postgres.stop();
    }

    // tests
}

⚠️ 虽然这种方式提供了细粒度控制,但配置繁琐。好在 Testcontainers 提供了更简单的 JDBC 支持方案。

3. 使用 Testcontainers JDBC 驱动

核心优势:通过特殊 JDBC URL 自动启动容器,无需手动管理生命周期。

3.1 配置方式

JDBC URL 格式:
jdbc:tc:<docker-image-name>:<image-tag>///database-name

示例配置(YAML):

spring.datasource.url: jdbc:tc:postgresql:16-alpine:///test-db

3.2 测试类实现

直接通过注解配置,无需容器管理代码:

@SpringBootTest(properties =
  "spring.datasource.url: jdbc:tc:postgresql:16-alpine:///test-db"
)
class CustomTestcontainersDriverLiveTest {
    @Autowired
    HobbitRepository theShire;

    @Test
    void whenCallingSave_thenEntityIsPersistedToDb() {
        theShire.save(new Hobbit("Frodo Baggins"));

        assertThat(theShire.findAll())
          .hasSize(1).first()
          .extracting(Hobbit::getName)
          .isEqualTo("Frodo Baggins");
    }
}

关键优势:Testcontainers 自动处理容器生命周期,开发者只需关注业务逻辑测试。

4. 总结

方案 优点 缺点
手动管理 灵活控制生命周期,可深度定制 代码冗余,配置复杂
JDBC 驱动 一行配置搞定,零样板代码 定制能力有限

推荐场景

  • 需要特殊容器配置 → 手动管理
  • 标准数据库测试 → JDBC 驱动(简单粗暴高效)

完整示例代码见 GitHub 仓库


原始标题:Testcontainers JDBC Support | Baeldung