Как проверить json тело запроса в MockRestServiceServer - PullRequest
1 голос
/ 28 января 2020

Мое приложение сериализует различные модели и отправляет их через HTTP-запросы третьей стороне.

Я бы хотел десериализовать тело запроса в ту или иную модель в зависимости от интеграционного теста, а затем утверждать его. Похоже, что некоторые люди могут реализовать свои собственные RequestMatcher или просто утверждать против строки, но обе эти опции кажутся грязными. Если бы я реализовал свой собственный RequestMatcher, мне бы пришлось реализовать разные RequestMatcher для каждой модели, которой могло бы быть тело (и их много).

Было бы неплохо, если бы я мог просто десериализовать json в теле запроса и делайте то, что я хочу, за пределами декларативного соответствия.

Примерно так:

BodyCaptor captor = new BodyCaptor(); // I made this up

MockRestServiceServer mockServer = MockRestServiceServer.bindTo(restTemplate).ignoreExpectOrder(true).build();

mockServer
    .expect(MockRestRequestMatchers.requestTo(testBaseUri + testApiPath))
    .andExpect(method(HttpMethod.POST))
    .andExpect(content().contentType(MediaType.APPLICATION_JSON))
    .andCaptureBody(captor)
    .andRespond(MockRestResponseCreators.withSuccess());

MyModel mymodel = objectMapper.deserialize(captor.getValue())

assertThat(mymodel.getWhateverProperty()).isEqualTo(5)
....

Возможно ли что-то подобное? Какие у меня варианты?

Ответы [ 2 ]

1 голос
/ 28 января 2020

Вы можете проверить свойства, используя MockRestRequestMatchers.jsonPath , чтобы проверить json свойство и его значение

mockServer
.expect(MockRestRequestMatchers.requestTo(testBaseUri + testApiPath))
.andExpect(method(HttpMethod.POST))
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
.andExpect(MockRestRequestMatchers.jsonPath("$.property", Matchers.equalToIgnoringCase("value")))
.andRespond(MockRestResponseCreators.withSuccess());
0 голосов
/ 06 апреля 2020

Я закончил тем, что написал один RequestMatcher, который использовал Джексона ObjectMapper и взял expectedObject. Таким образом, я мог бы десериализовать тип expectedObject и выполнить сравнение по полям.

public class MyRequestMatcher implements RequestMatcher {

    private static final Logger LOG = LoggerFactory.getLogger(MyRequestMatcher.class);

    private Object expectedPayload;

    private ObjectMapper objectMapper;

    public MyRequestMatcher (Object expectedPayload, ObjectMapper objectMapper) {
        this.expectedPayload = expectedPayload;
        this.objectMapper = objectMapper;
    }

    @Override
    public void match(ClientHttpRequest clientHttpRequest) throws IOException, AssertionError {
        byte[] requestBodyBytes = ((ByteArrayOutputStream)clientHttpRequest.getBody()).toByteArray();
        String requestBody = new String(requestBodyBytes, StandardCharsets.UTF_8);

        Object actualPayload = objectMapper.readValue(requestBody, expectedPayload.getClass());

        // do this in a try catch so we can log the meaningful message from our assertion 
        // library before rethrowing - otherwise it gets swallowed by mockServer
        try {
            assertThat(actualPayload).isEqualToComparingFieldByField(expectedPayload)
        } catch (AssertionError error) {
            LOG.error(error.getMessage());
            throw error;
        }
    }
}

Теперь я могу сделать что-то вроде следующего в тесте:

MyObject expectedPayload = new MyObject();
expectedPayload.setField1("expectedValueforField1");
expectedPayload.setField2("expectedValueforField2");

mockServer
    .expect(MockRestRequestMatchers
            .requestTo("http://myurl.com/mypath"))
    .andExpect(new MyRequestMatcher(expectedPayload, objectMapper))
    .andRespond(request -> {
        return MockRestResponseCreators.withSuccess().createResponse(request);
    });
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...