Как проверить строку в тело ответа с 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
пробовал некоторые трюки с content (), body (), но ничего не получилось.
8 ответов
можно назвать 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(print())
.andExpect(status().isBadRequest())
.andReturn();
String content = result.getResponse().getContentAsString();
// do what you will
@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"
Так это доказательство того, что он работает!
Spring MockMvc теперь имеет прямую поддержку JSON. Поэтому вы просто говорите:
.andExpect(content().json("{'message':'ok'}"));
и в отличие от сравнения строк, он скажет что-то вроде "отсутствует поле xyz" или "сообщение ожидается" ОК "получил " nok".
этот метод был введен весной 4.1.
читая эти ответы, я вижу много, относящегося к весенней версии 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, если хотите, но я не включил это здесь, поскольку это отклонялось бы от вопроса.
фактическое возвращение json выглядело бы так:
{
"data":"some value"
}
Весенняя безопасность @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.")));
}
взята с весны учебник
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
ссылка может быть найдена здесь
String body = mockMvc.perform(bla... bla).andReturn().getResolvedException().getMessage()
Это должно дать вам тело ответа. "Имя пользователя уже занято" в вашем случае.
для проверки конечного результата html вы можете получить весь вывод HTML кодом ниже и проверить сообщения в нем:
@Test
public void testHtmlOutput() throws Exception {
String htmlBody = this.restTemplate.getForObject("/mypage, String.class);
assertThat(htmlBody.contains("any message in html output"));
}
шаблон rest должен быть autowired:
@Autowired
private TestRestTemplate restTemplate;
и assertThat должен быть импортирован как статический метод:
import static org.assertj.core.api.Assertions.assertThat;