Как проверить строку в тело ответа с помощью mockMvc - программирование
Подтвердить что ты не робот

Как проверить строку в тело ответа с помощью mockMvc

У меня простой тест интеграции

    @Test
public void shouldReturnErrorMessageToAdminWhenCreatingUserWithUsedUserName() throws Exception {
    mockMvc.perform(post("/api/users").header("Authorization", base64ForTestUser).contentType(MediaType.APPLICATION_JSON)
            .content("{\"userName\":\"testUserDetails\",\"firstName\":\"xxx\",\"lastName\":\"xxx\",\"password\":\"xxx\"}"))
            .andDo(print())
            .andExpect(status().isBadRequest())
            .andExpect(?);
}

В последней строке я хочу сравнить строку, полученную в тело ответа, с ожидаемой строкой

И в ответ я получаю:

MockHttpServletResponse:
          Status = 400
   Error message = null
         Headers = {Content-Type=[application/json]}
    Content type = application/json
            Body = "Username already taken"
   Forwarded URL = null
  Redirected URL = null

Пробовал некоторые трюки с контентом(), body(), но ничего не получилось.

4b9b3361

Ответ 1

@Sotirios Delimanolis ответьте на эту работу, однако я искал сравнение строк в этом утверждении mockMvc

Итак, здесь

.andExpect(content().string("\"Username already taken - please try with different username\""));

Конечно, мое утверждение терпит неудачу:

java.lang.AssertionError: Response content expected:
<"Username already taken - please try with different username"> but was:<"Something gone wrong">

потому что:

  MockHttpServletResponse:
            Body = "Something gone wrong"

Итак, это доказательство того, что он работает!

Ответ 2

Вы можете вызвать andReturn() и использовать возвращенный объект MvcResult, чтобы получить содержимое как String.

Смотрите ниже:

MvcResult result = mockMvc.perform(post("/api/users").header("Authorization", base64ForTestUser).contentType(MediaType.APPLICATION_JSON)
            .content("{\"userName\":\"testUserDetails\",\"firstName\":\"xxx\",\"lastName\":\"xxx\",\"password\":\"xxx\"}"))
            .andDo(MockMvcResultHandlers.print())
            .andExpect(status().isBadRequest())
            .andReturn();

String content = result.getResponse().getContentAsString();
// do what you will

Ответ 3

Spring Теперь MockMvc имеет прямую поддержку JSON. Поэтому вы просто говорите:

.andExpect(content().json("{'message':'ok'}"));

и, в отличие от сравнения строк, он скажет что-то вроде "отсутствует поле xyz" или "сообщение" Ожидаемое "ok 'got' nok '.

Этот метод был введен в Spring 4.1.

Ответ 4

Читая эти ответы, я вижу много, относящихся к Spring версии 4.x, я использую версию 3.2.0 по разным причинам. Поэтому такие вещи, как поддержка json прямо из content(), невозможны.

Я обнаружил, что использование MockMvcResultMatchers.jsonPath действительно легко и работает. Ниже приведен пример тестирования метода post.

Бонус с этим решением состоит в том, что вы по-прежнему сопоставляете атрибуты, не полагаясь на полное сравнение строк json.

(Используя org.springframework.test.web.servlet.result.MockMvcResultMatchers)

String expectedData = "some value";
mockMvc.perform(post("/endPoint")
                .contentType(MediaType.APPLICATION_JSON)
                .content(mockRequestBodyAsString.getBytes()))
                .andExpect(status().isOk())
                .andExpect(MockMvcResultMatchers.jsonPath("$.data").value(expectedData));

Тело запроса было просто строкой json, которую вы можете легко загрузить из реального файла json mock data, если хотите, но я не включил его здесь, поскольку он отклонился бы от вопроса.

Фактический ответ json выглядел бы так:

{
    "data":"some value"
}

Ответ 5

Spring security @WithMockUser и hamcrest containsString matcher делает для простого и элегантного решения:

@Test
@WithMockUser(roles = "USER")
public void loginWithRoleUserThenExpectUserSpecificContent() throws Exception {
    mockMvc.perform(get("/index"))
            .andExpect(status().isOk())
            .andExpect(content().string(containsString("This content is only shown to users.")));
}

Больше примеров на github

Ответ 6

Взято из весеннего урока

    mockMvc.perform(get("/" + userName + "/bookmarks/"
            + this.bookmarkList.get(0).getId()))
            .andExpect(status().isOk())
            .andExpect(content().contentType(contentType))
            .andExpect(jsonPath("$.id", is(this.bookmarkList.get(0).getId().intValue())))
            .andExpect(jsonPath("$.uri", is("http://bookmark.com/1/" + userName)))
            .andExpect(jsonPath("$.description", is("A description")));

is доступен из import static org.hamcrest.Matchers.*;

jsonPath доступен из import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;

и ссылку на jsonPath можно найти здесь

Ответ 7

String body = mockMvc.perform(bla... bla).andReturn().getResolvedException().getMessage()

Это должно дать вам ответ. "Имя пользователя уже выполнено" в вашем случае.

Ответ 8

здесь более элегантный способ

mockMvc.perform(post("/retrieve?page=1&countReg=999999")
            .header("Authorization", "Bearer " + validToken))
            .andExpect(status().isOk())
            .andExpect(content().string(containsString("regCount")));

Ответ 9

Вот пример того, как проанализировать ответ JSON и даже как отправить запрос с bean-компонентом в форме JSON:

  @Autowired
  protected MockMvc mvc;

  private static final ObjectMapper MAPPER = new ObjectMapper()
    .configure(WRITE_DATES_AS_TIMESTAMPS, false)
    .configure(FAIL_ON_UNKNOWN_PROPERTIES, false)
    .registerModule(new JavaTimeModule());

  public static String requestBody(Object request) {
    try {
      return MAPPER.writeValueAsString(request);
    } catch (JsonProcessingException e) {
      throw new RuntimeException(e);
    }
  }

  public static <T> T parseResponse(MvcResult result, Class<T> responseClass) {
    try {
      String contentAsString = result.getResponse().getContentAsString();
      return MAPPER.readValue(contentAsString, responseClass);
    } catch (IOException e) {
      throw new RuntimeException(e);
    }
  }

  @Test
  public void testUpdate() {
    Book book = new Book();
    book.setTitle("1984");
    book.setAuthor("Orwell");
    MvcResult requestResult = mvc.perform(post("http://example.com/book/")
      .contentType(MediaType.APPLICATION_JSON)
      .content(requestBody(book)))
      .andExpect(status().isOk())
      .andReturn();
    UpdateBookResponse updateBookResponse = parseResponse(requestResult, UpdateBookResponse.class);
    assertEquals("1984", updateBookResponse.getTitle());
    assertEquals("Orwell", updateBookResponse.getAuthor());
  }

Как вы можете видеть здесь, Book является запросом DTO, а UpdateBookResponse является объектом ответа, анализируемым из JSON. Вы можете изменить конфигурацию Jakson ObjectMapper.