12

当使用 Spring Boot 构建微服务时,它很容易编写广泛且可读性强的集成测试并使用MockRestServiceServer.

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

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

通过将配置属性设置为 on 可以指定“集成/测试”是一个新端点@WebIntegrationTest,我可以成功模拟所有正在通过RestTemplate但不是 Zuul 转发处理的服务。

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

4

2 回答 2

8

查看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")));
    }
}
于 2016-07-26T21:12:20.213 回答
2

接受的答案具有主要思想。但我在某些方面挣扎,直到找出问题所在。所以我想用 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/

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

于 2019-08-22T14:13:14.530 回答