首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何测试Quarkus REST客户端接口?

如何测试Quarkus REST客户端接口?
EN

Stack Overflow用户
提问于 2020-04-28 23:15:53
回答 1查看 1.5K关注 0票数 2

我正在使用Quarkus中的MicroProfile REST客户端,想知道如何对自定义客户端接口进行单元测试?

示例服务:

代码语言:javascript
运行
复制
@Path("/v1")
@RegisterRestClient
public interface CustomService {

    @POST
    @Path("/custom")
    void postCustomObject(CustomObject object);
}

是否有可能编写一个涵盖此功能的单元测试?例如,我想测试请求正文是否被正确处理并包含正确的JSON (特别是因为我有一个问题,即JVM和本机映像模式之间的行为不同)。

使用REST-assured可以很容易地测试REST服务器资源,但我没有找到任何类似的REST客户端接口。

Quarkus guide on using the REST client也没有进一步帮助我,因为它使用了一个实际的服务来进行调用。在我的例子中,服务器端在构建/测试过程中不可用。

有什么建议吗?

EN

回答 1

Stack Overflow用户

发布于 2021-07-08 05:54:42

有点晚了,但我会尝试回答这个问题,以供将来参考。尽管我同意@Héctor的评论,但测试MicroProfile rest客户端本身(例如,实际测试错误处理程序)或在注入rest客户端的bean中可能会很有用。

无论如何,您需要一个模拟服务器,比如WireMock。Quarkus的官方指南实际上涵盖了这个topic。我可以在这里报告一个例子(我取自here)。

将此依赖项添加到您的pom.xml (如果您使用的是Maven):

代码语言:javascript
运行
复制
<dependency>
    <groupId>com.github.tomakehurst</groupId>
    <artifactId>wiremock-jre8</artifactId>
    <scope>test</scope>
    <version>${wiremock.version}</version> 
</dependency>

创建一个类,该类将在测试执行之前启动模拟服务器(并在测试全部执行后将其关闭):

代码语言:javascript
运行
复制
package org.acme.getting.started.country;

import java.util.Collections;
import java.util.Map;

import com.github.tomakehurst.wiremock.WireMockServer;
import io.quarkus.test.common.QuarkusTestResourceLifecycleManager;

import static com.github.tomakehurst.wiremock.client.WireMock.*;

public class WiremockCountries implements QuarkusTestResourceLifecycleManager {

    private WireMockServer wireMockServer;

    @Override
    public Map<String, String> start() {

        wireMockServer = new WireMockServer();
        wireMockServer.start();

        //define a static response when the request matches a url declared as a regex 
        stubFor(get(urlEqualTo("/v2/name/GR"))
                .willReturn(aResponse()
                        .withHeader("Content-Type", "application/json")
                        //read the WireMock docs: you can even use a json file in /resources/__files/ (default expected location) in place of a string
                        .withBody(
                        """
                        [
                            {
                                "name": "Ελλάδα",
                                "capital": "Αθήνα"
                            }
                        ]
                        """
                        )));
        //remap the base url of the external service to the base url of the mock server 
        return Collections.singletonMap("org.acme.getting.started.country.CountriesService/mp-rest/url", wireMockServer.baseUrl());
    }

    @Override
    public void stop() {
        if (null != wireMockServer) {
            wireMockServer.stop();
        }
    }
}

Memento:目前,您不能测试@Singleton bean,所以在rest客户端接口上添加注释@ApplicationScoped。

最后,在实际的测试类中使用这个类:

代码语言:javascript
运行
复制
package org.acme.getting.started.country;

import javax.inject.Inject;

import io.quarkus.test.common.QuarkusTestResource;
import io.quarkus.test.junit.QuarkusTest;
import org.eclipse.microprofile.rest.client.inject.RestClient;
import org.junit.jupiter.api.Test;

import static org.assertj.core.api.Assertions.assertThat;

@QuarkusTest
@QuarkusTestResource(WiremockCountries.class)
class RegularCountriesServiceTest {

    @Inject
    @RestClient
    CountriesService countriesService;

    @Test
    void testGR() {
//      assertThat(countriesService.getByName("GR")).hasSize(10).extracting("name").contains("Greece");
        assertThat(countriesService.getByName("GR")).hasSize(1).extracting("name").contains("Ελλάδα");
    }
}

如果您想测试上一级的rest客户端,您需要做的就是重用模拟服务器的包装器类,并使用@Inject注入将rest客户端声明为其依赖项的bean。这样做:

代码语言:javascript
运行
复制
@QuarkusTest
@QuarkusTestResource(WiremockWrapperAsBefore.class)
class MyBusinessClassTest {

    @Inject
    MyBusinessClass myBusinessClass;

    @Test
    void testMyRestCleintInjectedIntoMyBusinessClass() {

        ResponseDTO dto = myBusinessClass.methodWhichCallsMyMicroProfileRestClient(String someParam);
        assertNotNull(dto);
    }
}

否则,在其他场景中使用RestClientBuilder为MicroProfile rest客户端接口创建代理实现可能会很有用,如here所示

代码语言:javascript
运行
复制
import java.net.MalformedURLException;
import java.net.URI;
import org.eclipse.microprofile.rest.client.RestClientBuilder;
import static org.junit.Assert.assertNotNull;
import org.junit.Test;


public class RestClientTest {

    @Test
    public void init() throws MalformedURLException {
        URI baseURI = URI.create("http://localhost:8080");
        PingClient client = RestClientBuilder.newBuilder().
                baseUri(baseURI).
                build(PingClient.class);                
        assertNotNull(client);
        String result = client.ping();
        assertNotNull(result);
    }
}

对应的接口很容易猜到,但如下所示:

代码语言:javascript
运行
复制
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
        
@Path("/restclient/resources/ping")
@RegisterRestClient
public interface PingClient {

    @GET
    String ping();
}

在这种情况下,如果您正在使用Quarkus,则不需要以下依赖项,但我将从上面的链接报告,以防有人正在使用MicroProfile而不是Quarkus:

代码语言:javascript
运行
复制
<dependencies>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>javax</groupId>
        <artifactId>javaee-api</artifactId>
        <version>8.0</version>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>org.apache.cxf</groupId>
        <artifactId>cxf-rt-rs-mp-client</artifactId>
        <version>3.3.1</version>
        <scope>test</scope>
    </dependency>
</dependencies>  
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/61483728

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档