Spring启动+云| Zuul 代理 |集成测试

Spring Boot + Cloud | Zuul Proxy | Integration testing

当使用 Spring Boot 构建微服务时,使用 MockRestServiceServer.

编写广泛且易读的集成测试和模拟远程服务请求非常容易

有没有办法使用类似的方法对 ZuulProxy 执行额外的集成测试?我想要实现的是能够模拟 ZuulProxy 将转发到的远程服务器并验证我的所有 ZuulFitler 是否按预期运行。但是,ZuulProxy 使用的是 Netflix 的 RestClient(似乎已弃用?),它自然不会使用 RestTemplate,它可以由 MockRestServiceServer 重新配置,而我目前可以'找不到模拟远程服务对代理请求的响应的好方法。

我有一个微服务负责处理 API 会话密钥的创建,然后将类似于 API 网关。使用 Zuul Proxy 转发到底层暴露的服务,Zuul Filters 将检测 Session key 是否有效。因此,集成测试将创建一个有效会话,然后转发到一个假端点,例如 'integration/test'.

通过在 @WebIntegrationTest 上设置配置 属性 可以指定 'integration/test' 是一个新的端点,我可以成功地模拟通过 RestTemplate 处理的所有服务但不是 Zuul 转发。

实现转发目标服务模拟的最佳方法是什么?

查看 WireMock。我一直在使用它对我的 Spring Cloud Zuul 项目进行集成级别测试。

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

public class TestClass {
    @Rule
    public WireMockRule serviceA = new WireMockRule(WireMockConfiguration.options().dynamicPort());

    @Before
    public void before() {
        serviceA.stubFor(get(urlPathEqualTo("/test-path/test")).willReturn(aResponse()
            .withHeader("Content-Type", "application/json").withStatus(200).withBody("serviceA:test-path")));
    }

    @Test
    public void testRoute() {
        ResponseEntity<String> responseEntity = this.restTemplate.getForEntity("/test-path/test", String.class);
        assertThat(responseEntity.getStatusCode()).isEqualTo(HttpStatus.OK);

        serviceA.verify(1, getRequestedFor(urlPathEqualTo("/test-path/test")));
    }
}

接受的答案有主要思想。但在找出问题之前,我在某些方面苦苦挣扎。所以我想用 Wiremock 来展示一个更完整的答案。

测试:

@ActiveProfiles("test")
@TestPropertySource(locations = "classpath:/application-test.yml")
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@AutoConfigureWireMock(port = 5001)
public class ZuulRoutesTest {

    @LocalServerPort
    private int port;

    private TestRestTemplate restTemplate = new TestRestTemplate();

    @Before
    public void before() {

        stubFor(get(urlPathEqualTo("/1/orders/")).willReturn(aResponse()
                .withHeader("Content-Type", MediaType.TEXT_HTML_VALUE)
                .withStatus(HttpStatus.OK.value())));
    }

    @Test
    public void urlOrders() {
        ResponseEntity<String> result = this.restTemplate.getForEntity("http://localhost:"+this.port +"/api/orders/", String.class);
        assertEquals(HttpStatus.OK, result.getStatusCode());

        verify(1, getRequestedFor(urlPathMatching("/1/.*")));
    }
}

application-test.yml:

zuul:
  prefix: /api
  routes:
    orders:
      url: http://localhost:5001/1/
    cards:
      url: http://localhost:5001/2/

这应该有效。

但是 Wiremock 对我来说有一些限制。如果您在不同端口上有不同主机名 运行 的代理请求,如下所示:

zuul:
  prefix: /api
  routes:
    orders:
      url: http://lp-order-service:5001/
    cards:
      url: http://lp-card-service:5002/

同一端口上的本地主机 Wiremock 运行 将无法帮助您。我仍在尝试找到一个类似的集成测试,我可以在其中模拟来自 Spring 的 Bean 并阅读 url Zuul 代理在发出请求调用之前选择路由的内容。