在SpringBoot应用程序测试期间,RestClient无法到达自己的端点

h6my8fg2  于 12个月前  发布在  Spring
关注(0)|答案(1)|浏览(186)

域名

这是关于Spring Framework 6.1 M2(2023年7月)中引入的取代RestTemplate的RestClient的问题。

设置

  • SpringBoot v3.2.0(2023年11月)
  • 测试容器v1.19.3

场景

我已经使用了著名的TestRestTemplate -工作正常。但是因为我很好奇,我喜欢更上一层楼。

  • 如果我可以使用“真实的端点”,为什么要使用mocking(使用TestRestTemplate)?

换句话说:我想使用最近建立的Spring Framework的RestClient发送一个“真实的”请求。
解释:

  • 应用程序在其测试中将请求发送到其自己公开的端点。

动手吧

因此,我使用testcontainers设置了Java微服务。此外,应用程序上下文已完全加载(这是正确的吗?)

@SpringBootTest(
        webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
        properties = "spring.profiles.active=integrationtest"
)
@Testcontainers
@ContextConfiguration(initializers = {EndpointApplicationTest.Initializer.class})
class EndpointApplicationTest {
       ... .. . CODE . .. ...
}

字符串
此时,我希望应用程序公开其端口和Map。

问题

虽然RestClient可以很好地处理任何外部资源,但它不会访问自己的Map:

String url = "http://localhost:PORT/actuator";

        String givenAnswer = restClient.get()
                .uri(url)
                .retrieve()
                .body(String.class);


上面的代码片段失败,并显示:

org.springframework.web.client.ResourceAccessException: I/O error on GET request for "http://localhost:PORT/actuator": null


该服务仍然非常简单,没有设置进一步的安全性(例如https)。

附加执行器行为

手动运行应用程序(无测试运行,无测试容器),执行器按预期可用,例如通过浏览器(http://localhost:PORT/actuator)。

剩余问题

  1. SpringBoot在测试期间没有暴露其端口吗?
    1.我还错过了什么吗
eqzww0vc

eqzww0vc1#

TL;DR

@LocalServerPort->帮助我

推理

尽管Testcontainer与应用程序在端口(例如8081)打开了连接,但SpringBoot应用程序看不到。此外,missmatch令人恼火,因为应用程序应该在8081的容器内打开(参考application.yml中的配置)。尽管如此,在测试期间获胜的配置**是SpringBootTest.WebEnvironment.RANDOM_PORT
因此,每次运行时,localServerPort都会在上限范围(30000 < x < 65535)内发生变化。

示例代码

class EndpointApplicationTest {

    private static final Logger logger =
            LoggerFactory.getLogger(AuthEndpointApplicationTest.class);
    public static DockerComposeContainer<?> dcEnv;

    @Autowired
    private TestRestTemplate restTemplate;

    @LocalServerPort
    private int port;
    private final RestClient restClient = RestClient.create();

    @Test
    @DisplayName("Sample-Rest request")
    public void RequestTest() {

        // URLS
        String uriBase = String.format("http://localhost:%s/v1", port);
        logger.info(String.format("Port: %s for URL-Base: %s", port, uriBase));

        HttpHeaders headers = new HttpHeaders();
        headers.add("Content-Type", "application/json");

        Map<String, String> applicationJSON = new HashMap<>();
        applicationJSON.put("foo", "bar");

        // Rest call
        String response = restClient.post()
                .uri(uriBase + "/route")
                .contentType(APPLICATION_JSON)
                .body(applicationJSON)
                .retrieve()
                .body(String.class);
        assertEquals("Processed successfully", response);
    }

字符串

福利

1.测试更等同于运行环境,因为不需要faked RestTemplate

  1. java.net.HttpRetryException: cannot retry due to server authentication, in streaming mode不会抛出(与RestTemplate相比)..(注意:我个人的副作用)。
    1.可以决定是否返回ResponseEntity未 Package 的类
// Rest call
            ResponseEntity<String> response = restClient.post()                    
                    . .. ... .. .
                    .toEntity(String.class);

相关问题