You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用@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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 19:37:14