简体   繁体   English

Spring Boot + 云 | Zuul 代理 | 集成测试

[英]Spring Boot + Cloud | Zuul Proxy | Integration testing

When working with Spring Boot to build micro-services its very easy to write extensive and very readable integration tests and mock remote service requests with MockRestServiceServer .当使用 Spring Boot 构建微服务时,使用MockRestServiceServer编写广泛且非常易读的集成测试和模拟远程服务请求非常容易。

Is there a way to use similar approach to perform additional integration test on ZuulProxy ?有没有办法使用类似的方法在ZuulProxy上执行额外的集成测试? What I would like to achieve is being able to mock remote servers that ZuulProxy would forward to and validate that all of my ZuulFitler s behaved as expected.我想要实现的是能够模拟ZuulProxy将转发到的远程服务器并验证我的所有ZuulFitler的行为是否符合预期。 However, ZuulProxy is using RestClient from Netflix (deprecated it would seem?) which naturally does not use RestTemplate which could be re-configured by MockRestServiceServer and I currently can't find a good way of mocking responses from remote services for proxied requests.然而, ZuulProxy使用RestClient来自Netflix(不建议使用它似乎?),这自然不使用RestTemplate这可能是重新配置由MockRestServiceServer ,我目前还没有找到嘲讽从远程服务响应的代理请求的好方法。

I have a micro-service that is responsible for handling API Session Key creation and then will act similar to an API Gateway.我有一个微服务,负责处理 API 会话密钥的创建,然后将类似于 API 网关。 Forwarding is done with Zuul Proxy to underlying exposed services, and Zuul Filters will detect if Session key is valid or not.使用 Zuul 代理转发到底层公开的服务,Zuul 过滤器将检测会话密钥是否有效。 An integration test would therefore create a valid session and then forward to a fake endpoint, eg 'integration/test'.因此,集成测试将创建一个有效的会话,然后转发到一个假端点,例如“集成/测试”。

Specifying that 'integration/test' is a new endpoint is possible by setting a configuration property on @WebIntegrationTest , I can successfully mock all services that are being handled via RestTemplate but not Zuul forwarding.通过在@WebIntegrationTest上设置配置属性,可以指定“集成/测试”是一个新端点,我可以成功模拟所有通过RestTemplate处理但不是 Zuul 转发的服务。

What's the best way to do achieve mocking of a forward target service?实现模拟前向目标服务的最佳方法是什么?

Check out WireMock .查看WireMock I have been using it to do integration level testing of my Spring Cloud Zuul project.我一直在使用它对我的 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")));
    }
}

The accepted answer has the main idea.接受的答案具有主要思想。 But I struggle on some points until figure out the problem.但我在某些方面挣扎,直到找出问题所在。 So I would like to show a more complete answer using also Wiremock.所以我想用 Wiremock 展示一个更完整的答案。

The test:考试:

@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/.*")));
    }
}

And the application-test.yml :application-test.yml

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

This should work.这应该有效。

But Wiremock has some limitations for me.但是 Wiremock 对我有一些限制。 If you has proxy requests with different hostnames running on different ports, like this:如果您在不同端口上运行具有不同主机名的代理请求,如下所示:

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

A localhost Wiremock running on the same port will no be able to help you.在同一端口上运行的 localhost Wiremock 将无法帮助您。 I'm still trying to find a similar Integration Test where I could just mock a Bean from Spring and read what url the Zuul Proxy choose to route before it make the request call.我仍在尝试找到一个类似的集成测试,我可以在其中模拟 Spring 中的 Bean 并读取 Zuul 代理在发出请求调用之前选择路由的url

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM