Есть ли какой-либо подходящий сопоставитель для анализа и сравнения поля LocalDateTime в ответе Json от MockMvc

#java #testing #jsonpath #matcher #mockmvc

#java #тестирование #jsonpath #сопоставитель #mockmvc

Вопрос:

Я тестирую get метод моего контроллера SpringBoot, который предоставляет объекты, записанные в базе данных в определенном временном диапазоне.

Я понимаю, что могу получить json после выполнения MockMvc и проанализировать его с помощью object mapper, использовать несколько потоков и одно утверждение, но мне интересно, есть ли встроенный способ сделать это с помощью последовательности andExpect().

Я пробовал сопоставители даты Hamcrest, но он не может анализировать формат LocalDateTime
java.lang.AssertionError: JSON path "data.SENT[0].sentAt"
Expected: the date is within 10 days of "08 апр 2019 19:03:48 614ms 0300"
but: was "2019-04-02T11:36:16.51"

 this.mockMvc.perform(get(BASE_URL)
                .accept(MediaType.APPLICATION_JSON_VALUE)
                .contentType(MediaType.APPLICATION_JSON)
                .content(jsonMockObjectMapper.writeValueAsString(smsStatisticFullRequest)))
                .andExpect(status().isOk())
                .andExpect(jsonPath("data.SENT[*].sentAt", Matchers.hasItems("2019-04-02T11:36:16.51")))
//              .andExpect(jsonPath("data.SENT[0].sentAt", DateMatchers.within(10, TimeUnit.DAYS, Timestamp.valueOf(LocalDateTime.now()))))
//              .andExpect(jsonPath("data.SENT[0].sentAt", DateMatchers.before(Timestamp.valueOf(LocalDateTime.now()))))
                .andDo(CustomResultHandler.handleResult(name.getMethodName(), MockMvcRestDocumentation::document));
  

Я ожидаю, что смогу проверить, что все объекты в возвращаемых данных находятся в диапазоне времени утверждения.

 Content-Type: application/json;charset=UTF-8
Cache-Control: no-cache, no-store, max-age=0, must-revalidate

{
  "apiVersion" : "1.0.1",
  "error" : false,
  "data" : {
    "SENT" : [ {
      "id" : 3,
      "phone" : "9111233456",
      "userId" : 683581,
      "sentAt" : "2019-04-02T11:36:16.51",
      "operation" : "RECOVERY_PASSWORD",
      "smsCode" : "2112"
    } ],

  

Я могу проверить, есть ли какой-то конкретный объект. Но я не могу быть уверен, что в моих возвращаемых данных нет записей о периоде времени.

Ответ №1:

Я создал свой собственный сопоставитель:

 
import net.minidev.json.JSONArray;
import org.hamcrest.BaseMatcher;
import org.hamcrest.Description;

import java.time.LocalDateTime;

class CustomMatcher extends BaseMatcher<LocalDateTime> {

    private LocalDateTime from;
    private LocalDateTime to;
    private int misMatchAtIndex;

    CustomMatcher(LocalDateTime from, LocalDateTime to) {
        this.from = from;
        this.to = to;
    }

    @Override
    public boolean matches(Object item) {
        JSONArray rawData = (JSONArray) item;
        for (Object raw : rawData) {
            LocalDateTime parsed = LocalDateTime.parse(raw.toString());
            if (!parsed.isBefore(to) || !parsed.isAfter(from)) {
                misMatchAtIndex = rawData.indexOf(raw);
                return false;
            }
        }
        return true;
    }

    @Override
    public void describeTo(Description description) {
        description.appendText(String.format("All DateTime fields from %s to %s, mismatch at index %d",
                from, to, misMatchAtIndex));
    }
}
  

используйте:

  .andExpect(jsonPath("data."   SENT   "[*].sentAt", new CustomMatcher(fromDate, toDate)))