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

h6my8fg2  于 2024-01-06  发布在  Spring
关注(0)|答案(1)|浏览(210)

域名

这是关于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微服务。此外,应用程序上下文已完全加载(这是正确的吗?)

  1. @SpringBootTest(
  2. webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
  3. properties = "spring.profiles.active=integrationtest"
  4. )
  5. @Testcontainers
  6. @ContextConfiguration(initializers = {EndpointApplicationTest.Initializer.class})
  7. class EndpointApplicationTest {
  8. ... .. . CODE . .. ...
  9. }

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

问题

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

  1. String url = "http://localhost:PORT/actuator";
  2. String givenAnswer = restClient.get()
  3. .uri(url)
  4. .retrieve()
  5. .body(String.class);


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

  1. 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)内发生变化。

示例代码

  1. class EndpointApplicationTest {
  2. private static final Logger logger =
  3. LoggerFactory.getLogger(AuthEndpointApplicationTest.class);
  4. public static DockerComposeContainer<?> dcEnv;
  5. @Autowired
  6. private TestRestTemplate restTemplate;
  7. @LocalServerPort
  8. private int port;
  9. private final RestClient restClient = RestClient.create();
  10. @Test
  11. @DisplayName("Sample-Rest request")
  12. public void RequestTest() {
  13. // URLS
  14. String uriBase = String.format("http://localhost:%s/v1", port);
  15. logger.info(String.format("Port: %s for URL-Base: %s", port, uriBase));
  16. HttpHeaders headers = new HttpHeaders();
  17. headers.add("Content-Type", "application/json");
  18. Map<String, String> applicationJSON = new HashMap<>();
  19. applicationJSON.put("foo", "bar");
  20. // Rest call
  21. String response = restClient.post()
  22. .uri(uriBase + "/route")
  23. .contentType(APPLICATION_JSON)
  24. .body(applicationJSON)
  25. .retrieve()
  26. .body(String.class);
  27. assertEquals("Processed successfully", response);
  28. }

字符串

福利

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

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

展开查看全部

相关问题