如何实现存在依赖的QuarkusTestResourceLifecycleManager
Quarkus测试资源跨依赖传值实现方案
注意:
setContext方法传入的Context对象仅承载测试Profile元信息,设计上不用于跨资源传递业务配置,不要尝试往该对象塞自定义值,不同版本实现存在差异,会有兼容性问题。
跨资源依赖的实现有两种稳定可生产使用的方案,均为Quarkus官方支持的逻辑:
方案1:基于注解顺序+配置源传值(无侵入,推荐通用场景使用)
Quarkus加载@QuarkusTestResource标注的资源时,严格遵循注解声明的顺序初始化:先声明的资源先执行start(),其返回的配置键值对会实时注入测试阶段的全局配置源,后启动的资源可以直接通过Config API读取这些配置。
实现步骤:
- 在测试类上声明测试资源时,将被依赖的基础资源(如数据库资源)放在前面,依赖其他资源的业务资源放在后面,示例:
@QuarkusTestResource(DatabaseTestResource.class) @QuarkusTestResource(BusinessServiceTestResource.class) public class OrderServiceTest { // 测试逻辑 }
- 被依赖的基础资源在
start()方法返回的Map<String, String>中,把需要对外暴露的参数(如数据库IP、端口、连接串)全部写入,示例:
@Override public Map<String, String> start() { // 启动数据库容器逻辑 String dbIp = container.getHost(); Integer dbPort = container.getFirstMappedPort(); return Map.of( "custom.db.ip", dbIp, "custom.db.port", String.valueOf(dbPort), "quarkus.datasource.jdbc.url", String.format("jdbc:postgresql://%s:%d/test", dbIp, dbPort) ); }
- 依赖其他资源的业务资源,在自身
start()方法中通过ConfigProvider读取已注入的配置,拿到依赖参数后再完成自身初始化,示例:
@Override public Map<String, String> start() { Config testConfig = ConfigProvider.getConfig(); String dbIp = testConfig.getValue("custom.db.ip", String.class); Integer dbPort = testConfig.getValue("custom.db.port", Integer.class); // 拿到数据库连接信息后启动业务服务 this.service = BusinessService.connect(dbIp, dbPort); return Map.of("custom.service.endpoint", service.getEndpoint()); }
注意:不要用静态变量跨资源传值,Quarkus测试支持并行执行,静态变量会出现类加载隔离下的串值问题,走配置源传递是线程安全、符合隔离规范的实现。
方案2:资源内部嵌套管理生命周期(适合强绑定依赖场景)
如果两个资源是强绑定关系,不想靠注解书写顺序控制依赖,可以直接在依赖方资源内部手动实例化、管理被依赖资源的生命周期,不需要在测试类上声明多个资源注解。
实现示例:
public class BusinessServiceTestResource implements QuarkusTestResourceLifecycleManager { private final DatabaseTestResource dbResource = new DatabaseTestResource(); private BusinessService service; @Override public Map<String, String> start() { // 先启动依赖的数据库资源,直接拿到其返回的配置 Map<String, String> dbConfigs = dbResource.start(); String dbIp = dbConfigs.get("custom.db.ip"); Integer dbPort = Integer.parseInt(dbConfigs.get("custom.db.port")); // 初始化自身业务服务 this.service = BusinessService.connect(dbIp, dbPort); // 合并所有配置返回给Quarkus配置源 Map<String, String> allConfigs = new HashMap<>(dbConfigs); allConfigs.put("custom.service.endpoint", service.getEndpoint()); return allConfigs; } @Override public void stop() { // 按照启动逆序销毁资源:先停自身服务,再停数据库 if (service != null) { service.shutdown(); } dbResource.stop(); } }
这种实现下,测试类只需要添加@QuarkusTestResource(BusinessServiceTestResource.class)即可,依赖关系由资源自身管控,不会出现注解顺序写错导致的启动失败问题。
内容的提问来源于stack exchange,提问作者juangon
相关产品推荐
相关产品推荐

