0Pricing
Java Academy · 课时

Testcontainers:真实数据库集成测试

使用 Testcontainers 在 Docker 中启动 PostgreSQL,并针对真实数据库运行集成测试

Testcontainers:真实数据库集成测试 是 CoddyKit 上的免费 Java Academy 课时。 这是第 4 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Java Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Java Academy 课程共包含 4 节课。

为什么使用 Testcontainers?

H2 内存数据库不支持 PostgreSQL 特有的功能(JSON、全文搜索、ON CONFLICT)。Testcontainers 会在测试期间启动真实的 Docker 容器,为您提供与生产环境一致的数据库。

添加 Testcontainers 依赖

将 Testcontainers BOM 和 PostgreSQL 模块添加到构建文件中。Spring Boot 3.1+ 已包含受管理的 Testcontainers 版本。

// build.gradle:
testImplementation "org.testcontainers:junit-jupiter"
testImplementation "org.testcontainers:postgresql"
// Optionally use Spring Boot Testcontainers support:
testImplementation "org.springframework.boot:spring-boot-testcontainers"

@Testcontainers 和 @Container

使用 @Testcontainers 标注测试类,并将容器声明为静态的 @Container 字段。JUnit 5 会自动启动和停止它。

@Testcontainers
@DataJpaTest
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
class UserRepositoryIntegrationTest {
    @Container
    static PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>("postgres:16-alpine")
        .withDatabaseName("testdb")
        .withUsername("test")
        .withPassword("test");
}

从容器配置 DataSource

使用 @DynamicPropertySource 将容器的动态端口和凭据注入 Spring 的 DataSource 配置。

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

Spring Boot 3.1 ServiceConnection

Spring Boot 3.1+ 会从标注了 @Container 和 @ServiceConnection 的 Testcontainers Bean 自动配置数据源,无需使用 @DynamicPropertySource。

@Bean
@ServiceConnection
static PostgreSQLContainer<?> postgresContainer() {
    return new PostgreSQLContainer<>("postgres:16-alpine");
}

单例容器模式

每个测试类启动一个容器会很慢。请使用带有 Startables.deepStart() 的静态字段或抽象基类,让所有测试共享一个容器。

abstract class AbstractIntegrationTest {
    @Container
    static final PostgreSQLContainer<?> POSTGRES =
        new PostgreSQLContainer<>("postgres:16-alpine").withReuse(true);
    static { POSTGRES.start(); }
    @DynamicPropertySource
    static void props(DynamicPropertyRegistry r) {
        r.add("spring.datasource.url",      POSTGRES::getJdbcUrl);
        r.add("spring.datasource.username", POSTGRES::getUsername);
        r.add("spring.datasource.password", POSTGRES::getPassword);
    }
}

测试 PostgreSQL 特有功能

使用 Testcontainers,您可以测试 JSON 列、JSONB 运算符、全文搜索和 ON CONFLICT DO UPDATE,而这些功能无法使用 H2 测试。

@Test
void jsonb_search_works() {
    // Insert row with JSONB column, then query
    List<Event> logins = repo.findByType("login");
    assertEquals(1, logins.size());
}

多个容器:Compose

请使用 DockerComposeContainer 运行完整技术栈(PostgreSQL + Redis + Kafka),以支持需要多个服务的集成测试。

@Container
static DockerComposeContainer<?> compose = new DockerComposeContainer<>(
    new File("src/test/resources/docker-compose.yml"))
    .withExposedService("postgres", 5432)
    .withExposedService("redis", 6379);

Ryuk:自动清理

Testcontainers 使用 Ryuk 容器,在 JVM 退出时自动停止并删除容器,即使测试失败也不例外,从而防止容器泄漏。

使用 Testcontainers 的 @SpringBootTest

请使用 @SpringBootTest 而不是 @DataJpaTest,针对真实的 PostgreSQL 容器测试完整的应用程序技术栈(控制器、服务和存储库)。

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@Testcontainers
class FullIntegrationTest extends AbstractIntegrationTest {
    @LocalServerPort int port;
    @Autowired TestRestTemplate rest;
    @Test
    void end_to_end_user_creation() {
        ResponseEntity<UserDto> r = rest.postForEntity("/api/users", createReq(), UserDto.class);
        assertEquals(HttpStatus.CREATED, r.getStatusCode());
    }
}

容器镜像缓存

Testcontainers 会在本地缓存已拉取的 Docker 镜像。请在 CI 中运行测试前拉取镜像(docker pull postgres:16-alpine),避免测试运行期间产生下载开销。

快速检查

在 Spring Boot 3.1+ 中,哪个注解会将 Testcontainers 容器自动连接到 Spring 的数据源?

回顾

Testcontainers 会为集成测试运行真实的 Docker 容器。请使用 @Container + @DynamicPropertySource 或 @ServiceConnection(Boot 3.1+)。使用单例模式让多个测试共享容器。测试 H2 无法支持的 PostgreSQL 特有功能。

常见问题解答

「Testcontainers:真实数据库集成测试」课时是免费的吗?

是的 — 「Testcontainers:真实数据库集成测试」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Java Academy 课程的其余内容,请升级到 CoddyKit PRO。 Java Academy 课程共包含 4 节课。

「Testcontainers:真实数据库集成测试」这节课中我会学到什么?

使用 Testcontainers 在 Docker 中启动 PostgreSQL,并针对真实数据库运行集成测试 你通过在浏览器中直接运行的动手代码来练习 Java Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 Java Academy 需要有经验吗?

无需任何先前经验。CoddyKit 上的 Java Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 4 节课,共 4 节。

「Testcontainers:真实数据库集成测试」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 Java Academy 课中编写并运行代码吗?

能。每节 Java Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. 使用 @CsvSource 和 @MethodSource 编写参数化测试
  2. Mockito 进阶:参数捕获器与间谍
  3. Spring Boot 测试切片:@WebMvcTest 与 @DataJpaTest
  4. Testcontainers:真实数据库集成测试
← 返回 Java Academy