为 Spring 应用程序编写集成测试,其中使用的 RestTemplate 是 @LoadBalanced

问题描述

假设我创建了一个 RestTemplate Bean,如下所示:

    @Bean
    @LoadBalanced //Not working with tests
    public RestTemplate restTemplate(RestTemplateResponseErrorHandler handler){
        RestTemplate restTemplate = new RestTemplate();
        restTemplate.setErrorHandler(handler);
        restTemplate.setInterceptors(Collections.singletonList(
                new MyClientHttpRequestInterceptor())
        );
        return restTemplate;
    }

在控制器中,我使用它来调用外部服务。为了编写测试,我使用 MockWebServer 来模拟外部调用

@ExtendWith(SpringExtension.class)
@SpringBoottest(classes = RestApiTestingApplication.class,webEnvironment = SpringBoottest.WebEnvironment.RANDOM_PORT)
@AutoConfiguremockmvc
public class HttpBinControllerIT {

    public static MockWebServer mockBackEnd;
    @Autowired
    private mockmvc mvc;

    @BeforeAll
    static void setUp() throws IOException {
        mockBackEnd = new MockWebServer();
        mockBackEnd.start();
    }

    @DynamicPropertySource
    static void registerPgProperties(DynamicPropertyRegistry registry) {
        registry.add("my.service.url",() -> String.format("http://localhost:%s",mockBackEnd.getPort()));
    }


    @Afterall
    static void tearDown() throws IOException {
        mockBackEnd.shutdown();
    }

    @Test
    public void restTemplateGet_200() throws Exception {

        final dispatcher dispatcher = new dispatcher() {
            @Override
            public MockResponse dispatch(RecordedRequest request) {
                switch (request.getPath()) {
                    case "/get":
                        if(!request.getHeader("foo").isEmpty() &&
                                request.getHeader("foo").equalsIgnoreCase("foovalue"))
                        return new MockResponse().setResponseCode(200).setBody("test");
                }
                return new MockResponse().setResponseCode(404);
            }

        mockBackEnd.setdispatcher(dispatcher);

        mvc.perform(get("/bin/rest/get")
                .contentType(MediaType.APPLICATION_JSON))
                .andExpect(status().isOk())
                .andExpect(result -> {
                    result.equals("test");
                });
    }
}

我在测试中遇到以下异常:

2021-06-20 04:30:51.344  WARN 86739 --- [oundedElastic-1] o.s.c.l.core.RoundRobinLoadBalancer      : No servers available for service: localhost

org.springframework.web.util.nestedservletexception: Request processing Failed; nested exception is java.lang.IllegalStateException: No instances available for localhost

如果我注释掉 @LoadBalanced,则所有测试都有效。

如何在测试中禁用负载平衡?

注意 - 虽然可能有另一种方法来测试或创建 resttempalte bean 测试。这只是一个示例。实际上,我没有创造它的自由。它来自一个具有自定义配置的休息模板的自定义 jar。

示例项目是 here

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)