1. 概述
本文将展示如何使用 Testcontainers 对 Quarkus 应用进行"真实"的服务间测试。
在微服务架构中,测试至关重要,但重现生产环境往往很困难。常见的测试方案包括:
- 使用 Postman 等手动 API 测试工具
- 模拟服务依赖(Mocking)
- 依赖内存数据库
⚠️ 这些方案可能导致服务间的真实交互直到 CI 阶段或部署到生产环境才被验证,容易造成交付延迟。
Testcontainers 提供了优雅的解决方案:它能在本地测试环境中动态启动依赖服务,让我们直接与容器化的应用、服务或依赖进行交互测试。
2. 解决方案架构
我们的架构设计简洁明了,专注于验证 Testcontainers 在服务间测试中的价值:
核心流程:
- 客户端调用 customer-service(被测系统)
- customer-service 从 order-service 获取客户订单数据
- 每个服务都有独立的 PostgreSQL 数据库支撑
3. Testcontainers 实现方案
3.1 添加依赖
首先确保添加以下核心依赖(Maven):
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>testcontainers</artifactId>
<version>1.19.6</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>postgresql</artifactId>
<version>1.19.6</version>
<scope>test</scope>
</dependency>
3.2 测试资源管理器
Quarkus 提供了关键的测试管理类。根据官方文档:
"在测试启动前,常需要启动 Quarkus 应用依赖的服务。为此,Quarkus 提供了
@QuarkusTestResource
和QuarkusTestResourceLifecycleManager
"
创建测试资源管理器类:
public class CustomerServiceTestcontainersManager implements QuarkusTestResourceLifecycleManager {
}
3.3 容器配置
使用 Testcontainers API 预配置的模块来管理依赖:
private PostgreSQLContainer<?> postgreSQLContainer;
private GenericContainer<?> orderService;
实现服务启动逻辑:
@Override
public Map<String, String> start() {
// 容器启动配置代码(原文未展开)
}
测试结束后清理资源:
@Override
public void stop() {
if (orderService != null) {
orderService.stop();
}
if (postgreSQLContainer != null) {
postgreSQLContainer.stop();
}
}
3.4 测试类集成
通过注解让 Quarkus 自动管理依赖生命周期:
@QuarkusTestResource(CustomerServiceTestcontainersManager.class)
class CustomerResourceLiveTest {
}
3.5 参数化测试
编写测试验证客户数据及订单获取:
@ParameterizedTest
@MethodSource(value = "customerDataProvider")
void givenCustomer_whenFindById_thenReturnOrders(long customerId, String customerName, int orderSize) {
Customer response = RestAssured.given()
.pathParam("id", customerId)
.get()
.thenReturn()
.as(Customer.class);
Assertions.assertEquals(customerId, response.id);
Assertions.assertEquals(customerName, response.name);
Assertions.assertEquals(orderSize, response.orders.size());
}
private static Stream<Arguments> customerDataProvider() {
return Stream.of(Arguments.of(1, "Customer 1", 3), Arguments.of(2, "Customer 2", 1), Arguments.of(3, "Customer 3", 0));
}
3.6 执行结果
测试运行时输出显示 order-service 容器成功启动:
Creating container for image: quarkus/order-service-jvm:latest
Container quarkus/order-service-jvm:latest is starting: 02ae38053012336ac577860997f74391eef3d4d5cd07cfffba5e27c66f520d9a
Container quarkus/order-service-jvm:latest started in PT1.199365S
✅ 我们成功实现了生产级别的真实依赖测试,端到端验证了服务行为。
4. 总结
本文展示了 Testcontainers 如何通过容器化依赖解决 Quarkus 应用的测试难题。核心优势包括:
- ✅ 直接与真实服务交互,保证测试可靠性
- ✅ 提供编程式 API 简化测试代码
- ✅ 避免模拟服务带来的测试偏差
- ✅ 支持任意容器化依赖
这种方案踩坑少、简单粗暴,特别适合微服务架构的集成测试场景。
完整源码可在 GitHub 获取。