Предположим, что я пишу тесты интеграции Spring для службы REST A. Эта служба, в свою очередь, попадает в другую службу REST B и получает список URI, которые попадают в REST service C. Это своего рода шаблон автоматического обнаружения. Я хочу издеваться над ответами B и C с помощью MockRestServiceServer.
Теперь ответ от B список URI, они все очень похожи, и для примера позволяет сказать, что мой ответ от B, как так:Spring MockRestServiceServer обрабатывает несколько запросов к одному и тому же URI (автообнаружение)
{
uris: ["/stuff/1.json", "/stuff/2.json", "/stuff/39.json", "/stuff/47.json"]
}
Просто обслуживание А будет добавлять каждый из их на базовый URL для службы C и сделать эти запросы.
Mocking B легко, так как это всего лишь 1 запрос.
Mocking C - это хлопот, так как я должен был бы издеваться над каждым URI для соответствующего макетного ответа. Я хочу автоматизировать его!
Итак, сначала я пишу мои собственные согласовани, чтобы соответствовать не полному URL, но часть его:
public class RequestContainsUriMatcher implements RequestMatcher {
private final String uri;
public RequestContainsUriMatcher(String uri){
this.uri = uri;
}
@Override
public void match(ClientHttpRequest clientHttpRequest) throws IOException, AssertionError {
assertTrue(clientHttpRequest.getURI().contains(uri));
}
}
Это прекрасно работает, теперь я могу это сделать:
public RequestMatcher requestContainsUri(String uri) {
return new RequestContainsUriMatcher(uri);
}
MockRestServiceServer.createServer(restTemplate)
.expect(requestContainsUri("/stuff"))
.andExpect(method(HttpMethod.GET))
.andRespond(/* I will get to response creator */);
Теперь мне нужно творец ответа, который знает полный URL запроса и где издеваться данные сидят (у меня будет как JSon файлы в папке тестовых ресурсов):
public class AutoDiscoveryCannedDataResponseCreator implements ResponseCreator {
private final Function<String, String> cannedDataBuilder;
public AutoDiscoveryCannedDataResponseCreator(Function<String, String> cannedDataBuilder) {
this.cannedDataBuilder = cannedDataBuilder;
}
@Override
public ClientHttpResponse createResponse(ClientHttpRequest clientHttpRequest) throws IOException {
return withSuccess(cannedDataBuilder.apply(requestUri), MediaType.APPLICATION_JSON)
.createResponse(clientHttpRequest);
}
}
Теперь материал легко, я ВГ e, чтобы написать строитель, который принимает URI запроса как строку и возвращает mock данные, как String! Brilliant!
public ResponseCreator withAutoDetectedCannedData() {
Function<String, String> cannedDataBuilder = new Function<String, String>() {
@Override
public String apply(String requestUri) {
//logic to get the canned data based on URI
return cannedData;
}
};
return new AutoDiscoveryCannedDataResponseCreator(cannedDataBuilder);
}
MockRestServiceServer.createServer(restTemplate)
.expect(requestContainsUri("/stuff"))
.andExpect(method(HttpMethod.GET))
.andRespond(withAutoDetectedCannedData());
Все работает отлично! .... Для первого запроса.
После первого запроса (/stuff/1.json) мой MockRestServiceServer отвечает сообщением «Ошибка подтверждения: дальнейших ожиданий не ожидается».
В принципе, я могу сделать столько запросов на этот MockRestServiceServer, сколько было .expect() на нем. И поскольку у меня было только 1 из них, только первый запрос будет проходить.
Есть ли способ вокруг него? Я действительно не хочу издеваться над сервисом C 10 или 20 раз ...
Благодарность за реализацию RequestContainsUriMatcher – Silentbang