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
.
Is there a way to use similar approach to perform additional integration test on 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. 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.
I have a micro-service that is responsible for handling API Session Key creation and then will act similar to an API Gateway. Forwarding is done with Zuul Proxy to underlying exposed services, and Zuul Filters will detect if Session key is valid or not. An integration test would therefore create a valid session and then forward to a fake endpoint, e.g '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.
What's the best way to do achieve mocking of a forward target service?
Apigee, Eureka, Kong, HAProxy, and Istio are the most popular alternatives and competitors to Zuul.
Zuul is the library used to provide the reverse proxy, based on the route it will forward to configure URL or service-id by passing the necessary information.
GitHub - rishabhverma17/microservice-zuul-without-eureka: This service can be used to create microservice architecture with Gateway/Reverse Proxy using Zuul without using Eureka. This service can be used to create microservice architecture with Gateway/Reverse Proxy using Zuul without using Eureka.
Zuul Server is a gateway application that handles all the requests and does the dynamic routing of microservice applications. The Zuul Server is also known as Edge Server.
Check out WireMock. I have been using it to do integration level testing of my Spring Cloud Zuul project.
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.
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
:
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. 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. 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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With