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 反馈 — 无需本地设置。
此课程中的所有课时
- 使用 @CsvSource 和 @MethodSource 编写参数化测试
- Mockito 进阶:参数捕获器与间谍
- Spring Boot 测试切片:@WebMvcTest 与 @DataJpaTest
- Testcontainers:真实数据库集成测试