Java 如何使用mockMvc检查响应正文中的字符串
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/18336277/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to check String in response body with mockMvc
提问by pbaranski
I have simple integration test
我有简单的集成测试
@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(?);
}
In last line I want to compare string received in response body to expected string
在最后一行中,我想将响应正文中收到的字符串与预期的字符串进行比较
And in response I get:
作为回应,我得到:
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
Tried some tricks with content(), body() but nothing worked.
用 content(), body() 尝试了一些技巧,但没有任何效果。
采纳答案by pbaranski
@Sotirios Delimanolis answer do the job however I was looking for comparing strings within this mockMvc assertion
@Sotirios Delimanolis 回答完成了这项工作,但是我正在寻找在这个 mockMvc 断言中比较字符串
So here it is
所以这里是
.andExpect(content().string("\"Username already taken - please try with different username\""));
Of course my assertion fail:
当然我的断言失败了:
java.lang.AssertionError: Response content expected:
<"Username already taken - please try with different username"> but was:<"Something gone wrong">
because:
因为:
MockHttpServletResponse:
Body = "Something gone wrong"
So this is proof that it works!
所以这证明它有效!
回答by Sotirios Delimanolis
You can call andReturn()
and use the returned MvcResult
object to get the content as a String
.
您可以调用andReturn()
并使用返回的MvcResult
对象将内容作为String
.
See below:
见下文:
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
回答by vertti
Spring MockMvc now has direct support for JSON. So you just say:
Spring MockMvc 现在直接支持 JSON。所以你只要说:
.andExpect(content().json("{'message':'ok'}"));
and unlike string comparison, it will say something like "missing field xyz" or "message Expected 'ok' got 'nok'.
与字符串比较不同的是,它会说“缺少字段 xyz”或“消息预期 'ok' 得到 'nok'。
This method was introduced in Spring 4.1.
这个方法是在 Spring 4.1 中引入的。
回答by justAnotherGuy
String body = mockMvc.perform(bla... bla).andReturn().getResolvedException().getMessage()
This should give you the body of the response. "Username already taken" in your case.
这应该给你响应的正文。在您的情况下,“用户名已被占用”。
回答by Jeremy
Reading these answers, I can see a lot relating to Spring version 4.x, I am using version 3.2.0 for various reasons. So things like json support straight from the content()
is not possible.
阅读这些答案,我可以看到很多与 Spring 4.x 版相关的内容,出于各种原因,我正在使用 3.2.0 版。所以像 json 直接支持这样的事情content()
是不可能的。
I found that using MockMvcResultMatchers.jsonPath
is really easy and works a treat. Here is an example testing a post method.
我发现使用MockMvcResultMatchers.jsonPath
真的很容易,而且效果很好。这是一个测试 post 方法的示例。
The bonus with this solution is that you're still matching on attributes, not relying on full json string comparisons.
这个解决方案的好处是你仍然匹配属性,而不是依赖于完整的 json 字符串比较。
(Using org.springframework.test.web.servlet.result.MockMvcResultMatchers
)
(使用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));
The request body was just a json string, which you can easily load from a real json mock data file if you wanted, but I didnt include that here as it would have deviated from the question.
请求正文只是一个 json 字符串,如果需要,您可以轻松地从真正的 json 模拟数据文件中加载它,但我没有在此处包含它,因为它会偏离问题。
The actual json returned would have looked like this:
返回的实际 json 看起来像这样:
{
"data":"some value"
}
回答by Michael W
Spring security's @WithMockUser
and hamcrest's containsString
matcher makes for a simple and elegant solution:
Spring security@WithMockUser
和 hamcrest 的containsString
匹配器提供了一个简单而优雅的解决方案:
@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.")));
}
回答by user2829759
Taken from spring's tutorial
取自 spring 的教程
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
is available from import static org.hamcrest.Matchers.*;
is
可从 import static org.hamcrest.Matchers.*;
jsonPath
is available from import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
jsonPath
可从 import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
and jsonPath
reference can be found here
和jsonPath
参考可以在这里找到
回答by Ricardo Ribeiro
here a more elegant way
这里有一种更优雅的方式
mockMvc.perform(post("/retrieve?page=1&countReg=999999")
.header("Authorization", "Bearer " + validToken))
.andExpect(status().isOk())
.andExpect(content().string(containsString("regCount")));
回答by Sergey Ponomarev
Here is an example how to parse JSON response and even how to send a request with a bean in JSON form:
这是一个如何解析 JSON 响应,甚至如何使用 JSON 形式的 bean 发送请求的示例:
@Autowired
protected MockMvc mvc;
private static final ObjectMapper MAPPER = new ObjectMapper()
.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false)
.configure(DeserializationFeature.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());
}
As you can see here the Book
is a request DTO and the UpdateBookResponse
is a response object parsed from JSON. You may want to change the Jakson's ObjectMapper
configuration.
正如您在此处看到的,这Book
是一个请求 DTO,而UpdateBookResponse
是从 JSON 解析的响应对象。您可能想要更改 Jakson 的ObjectMapper
配置。
回答by Hari Krishna
You can use 'getContentAsString' method to get the response data as string.
您可以使用 'getContentAsString' 方法以字符串形式获取响应数据。
String payload = "....";
String apiToTest = "....";
MvcResult mvcResult = mockMvc.
perform(post(apiToTest).
content(payload).
contentType(MediaType.APPLICATION_JSON)).
andReturn();
String responseData = mvcResult.getResponse().getContentAsString();
You can refer this linkfor test application.
您可以参考此链接进行测试应用程序。