如何使用mockMvc检查响应正文中的string

我有简单的集成testing

@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(?); } 

在最后一行,我想比较收到的响应正文string和预期的string

作为回应,我得到:

 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 

尝试了一些与内容(),身体()的技巧,但没有任何工作。

您可以调用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断言中的string

所以在这里

 .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" 

所以这certificate了它的工作原理!

Spring MockMvc现在直接支持JSON。 所以你只是说:

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

而不像string比较,它会说类似“缺less领域xyz”或“消息预期”确定“得到”nok“。

这个方法在Spring 4.1中引入。

阅读这些答案,我可以看到很多与Spring 4.x版本相关的内容,由于各种原因我正在使用3.2.0版本。 所以像json支持直接从content()是不可能的。

我发现使用MockMvcResultMatchers.jsonPath是非常容易的,而且是一种享受。 这里是一个testingpost方法的例子。

这个解决scheme的好处是,你仍然在匹配的属性,而不是依靠完整的JSONstring比较。

(使用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)); 

请求体只是一个JSONstring,如果你想,你可以很容易地从一个真正的JSON模拟数据文件加载,但我没有包括在这里,因为它会偏离问题。

实际返回的json看起来像这样:

 { "data":"some value" } 
 String body = mockMvc.perform(bla... bla).andReturn().getResolvedException().getMessage() 

这应该给你的回应的身体。 “您的用户名已被占用”。

Spring Security的@WithMockUser和hamcrest的containsString匹配器为一个简单而优雅的解决scheme:

 @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的例子