Spring Загрузка + облако | Zuul Proxy | Интеграционное тестирование
При работе с Spring Boot для создания микросервисов очень легко писать обширные и очень читаемые интеграционные тесты и макетировать запросы удаленных сервисов с помощью MockRestServiceServer
.
Есть ли способ использовать аналогичный подход для выполнения дополнительного теста интеграции на ZuulProxy
? То, что я хотел бы достичь, - это возможность издеваться над удаленными серверами, которые ZuulProxy
будет передавать и проверять, что все мои ZuulFitler
вели себя как ожидалось. Тем не менее, ZuulProxy
использует RestClient
из Netflix (устарел, казалось бы?), Который, естественно, не использует RestTemplate
, который может быть повторно настроен на MockRestServiceServer
, и я в настоящее время не могу найти хороший способ насмешек из удаленных служб для проксированных запросов.
У меня есть микросервис, который отвечает за обработку создания ключа сеанса API, а затем будет действовать аналогично шлюзу API. Пересылка осуществляется с помощью Zuul Proxy для лежащих в основе служб, а Zuul Filters обнаруживает, что ключ сеанса действителен или нет. Таким образом, интеграционный тест создаст действительный сеанс, а затем перейдет на поддельную конечную точку, например "интеграция/тест".
Задание того, что "интеграция/тест" является новой конечной точкой, возможно, установив свойство конфигурации на @WebIntegrationTest
, я могу успешно издеваться над всеми службами, которые обрабатываются с помощью RestTemplate
, но не для перенаправления Zuul.
Каков наилучший способ добиться издевательства в прямом целевом сервисе?
Ответы
Ответ 1
Проверьте 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")));
}
}
Ответ 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/
Локальный Wiremock, работающий на том же порту, не сможет вам помочь. Я все еще пытаюсь найти аналогичный интеграционный тест, в котором я мог бы просто смоделировать Бин из Spring и прочитать, что url
прокси Zuul выбирает для маршрутизации, прежде чем он сделает запрос запроса.