如何使用@QuarkusComponentTest对@RestClient进行单元测试?
解决Quarkus REST Client隔离单元测试问题
针对你遇到的隔离测试需求,提供两种可行方案,分别适配基于Quarkus轻量容器和完全脱离容器的场景:
方案一:基于@QuarkusComponentTest的正确配置
你之前的错误是因为@QuarkusComponentTest默认未加载REST Client相关扩展,导致ArC容器无法识别@RestClient限定符,也无法生成客户端代理。按以下步骤调整:
1. 补充测试依赖
确保pom.xml(或build.gradle)包含以下依赖:
<!-- Quarkus组件测试核心依赖 --> <dependency> <groupId>io.quarkus</groupId> <artifactId>quarkus-test-component</artifactId> <scope>test</scope> </dependency> <!-- REST Client扩展 --> <dependency> <groupId>io.quarkus</groupId> <artifactId>quarkus-rest-client</artifactId> <scope>test</scope> </dependency> <!-- 序列化/反序列化依赖(以Jackson为例) --> <dependency> <groupId>io.quarkus</groupId> <artifactId>quarkus-rest-client-jackson</artifactId> <scope>test</scope> </dependency> <!-- WireMock依赖 --> <dependency> <groupId>com.github.tomakehurst</groupId> <artifactId>wiremock-jre8</artifactId> <scope>test</scope> </dependency>
2. 编写测试类与WireMock资源
import io.quarkus.test.component.QuarkusComponentTest; import io.quarkus.test.common.QuarkusTestResource; import io.quarkus.test.common.QuarkusTestResourceLifecycleManager; import jakarta.inject.Inject; import org.eclipse.microprofile.rest.client.inject.RestClient; import org.junit.jupiter.api.Test; import static com.github.tomakehurst.wiremock.client.WireMock.*; @QuarkusComponentTest(extensions = {io.quarkus.rest.client.RestClientExtension.class, io.quarkus.jackson.JacksonExtension.class}) @QuarkusTestResource(WireMockTestResource.class) public class MyApiTest { @Inject @RestClient MyApi myApi; @Test void testRequestSerialization() { // 配置WireMock校验请求格式 stubFor(post(urlEqualTo("/api/your-endpoint")) .withRequestBody(matchingJsonPath("$.requestField", equalTo("expected-value"))) .willReturn(aResponse() .withStatus(200) .withHeader("Content-Type", "application/json") .withBody("{\"responseField\": \"success\"}"))); // 调用客户端并断言结果 var response = myApi.sendRequest(new RequestDto("expected-value")); assert response.getStatus() == 200; var result = response.readEntity(ResponseDto.class); assert "success".equals(result.getResponseField()); } // 自定义WireMock测试资源,负责启停服务并暴露端口 public static class WireMockTestResource implements QuarkusTestResourceLifecycleManager { private com.github.tomakehurst.wiremock.WireMockServer wireMockServer; @Override public java.util.Map<String, String> start() { wireMockServer = new com.github.tomakehurst.wiremock.WireMockServer(com.github.tomakehurst.wiremock.core.WireMockConfiguration.options().dynamicPort()); wireMockServer.start(); return java.util.Collections.singletonMap("wiremock.port", String.valueOf(wireMockServer.port())); } @Override public void stop() { if (wireMockServer != null) wireMockServer.stop(); } } }
3. 添加测试配置
在src/test/resources/application.properties中配置REST Client指向WireMock:
quarkus.rest-client."com.yourpackage.MyApi".url=http://localhost:${wiremock.port} # 禁用或替换真实环境的令牌拦截器(根据你的客户端配置调整) # quarkus.rest-client."com.yourpackage.MyApi".register-providers=com.yourpackage.TestTokenInterceptor
方案二:完全脱离Quarkus容器的独立测试
如果需要在Quarkus应用外测试REST Client,可以直接使用MicroProfile的RestClientBuilder手动构建客户端:
1. 补充依赖
<dependency> <groupId>org.eclipse.microprofile</groupId> <artifactId>microprofile-rest-client-api</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>io.quarkus</groupId> <artifactId>quarkus-rest-client-jackson</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>com.github.tomakehurst</groupId> <artifactId>wiremock-jre8</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-api</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-engine</artifactId> <scope>test</scope> </dependency>
2. 编写独立测试类
import com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider; import org.eclipse.microprofile.rest.client.RestClientBuilder; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import java.net.URI; import static com.github.tomakehurst.wiremock.client.WireMock.*; public class MyApiStandaloneTest { private static com.github.tomakehurst.wiremock.WireMockServer wireMockServer; private static MyApi myApi; @BeforeAll static void setUp() { wireMockServer = new com.github.tomakehurst.wiremock.WireMockServer(com.github.tomakehurst.wiremock.core.WireMockConfiguration.options().dynamicPort()); wireMockServer.start(); // 手动构建REST Client,注册序列化提供者 myApi = RestClientBuilder.newBuilder() .baseUri(URI.create(wireMockServer.baseUrl())) .register(JacksonJsonProvider.class) // 替换真实令牌拦截器为测试实现 // .register(new TestTokenInterceptor()) .build(MyApi.class); } @AfterAll static void tearDown() { wireMockServer.stop(); } @Test void testResponseParsing() { stubFor(get(urlEqualTo("/api/data")) .willReturn(aResponse() .withStatus(200) .withHeader("Content-Type", "application/json") .withBody("{\"id\": 1, \"name\": \"test-data\"}"))); var data = myApi.getData(); assert data.getId() == 1; assert "test-data".equals(data.getName()); } }
错误原因解释
Annotation is not a registered qualifier: @RestClient:@QuarkusComponentTest默认未加载REST Client扩展,导致ArC容器无法识别该限定符,需通过extensions属性显式指定相关扩展。- 移除
@RestClient后找不到组件:REST Client接口需要Quarkus生成代理类,@RestClient是容器识别并生成代理的标识,缺失则无法创建对应组件。
内容的提问来源于stack exchange,提问作者Chop
相关产品推荐
相关产品推荐

