[英]How to check String in response body with 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() 嘗試了一些技巧,但沒有任何效果。
您可以調用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
@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”或“消息預期 'ok' 得到 'nok'。
此方法是在 Spring 4.1 中引入的。
閱讀這些答案,我可以看到很多與 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 模擬數據文件中加載它,但我沒有在此處包含它,因為它會偏離問題。
返回的實際 json 如下所示:
{
"data":"some value"
}
取自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
從import static org.hamcrest.Matchers.*;
jsonPath
可從import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
和jsonPath
參考可以在這里找到
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.")));
}
一種可能的方法是簡單地包含gson
依賴項:
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
</dependency>
並解析值以進行驗證:
@RunWith(SpringRunner.class)
@WebMvcTest(HelloController.class)
public class HelloControllerTest {
@Autowired
private MockMvc mockMvc;
@MockBean
private HelloService helloService;
@Before
public void before() {
Mockito.when(helloService.message()).thenReturn("hello world!");
}
@Test
public void testMessage() throws Exception {
MvcResult mvcResult = mockMvc.perform(MockMvcRequestBuilders.get("/"))
.andExpect(status().isOk())
.andExpect(content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON_VALUE))
.andReturn();
String responseBody = mvcResult.getResponse().getContentAsString();
ResponseDto responseDto
= new Gson().fromJson(responseBody, ResponseDto.class);
Assertions.assertThat(responseDto.message).isEqualTo("hello world!");
}
}
這里有更優雅的方式
mockMvc.perform(post("/retrieve?page=1&countReg=999999")
.header("Authorization", "Bearer " + validToken))
.andExpect(status().isOk())
.andExpect(content().string(containsString("regCount")));
這是一個如何解析 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());
}
正如您在此處看到的, Book
是一個請求 DTO,而UpdateBookResponse
是一個從 JSON 解析的響應對象。 您可能想要更改 Jackson 的ObjectMapper
配置。
另一種選擇是:
when:
def response = mockMvc.perform(
get('/path/to/api')
.header("Content-Type", "application/json"))
then:
response.andExpect(status().isOk())
response.andReturn().getResponse().getContentAsString() == "what you expect"
您可以使用getContentAsString
方法將響應數據作為字符串獲取。
String payload = "....";
String apiToTest = "....";
MvcResult mvcResult = mockMvc.
perform(post(apiToTest).
content(payload).
contentType(MediaType.APPLICATION_JSON)).
andReturn();
String responseData = mvcResult.getResponse().getContentAsString();
您可以參考此鏈接進行測試應用程序。
String body = mockMvc.perform(bla... bla).andReturn().getResolvedException().getMessage()
這應該為您提供響應的主體。 在您的情況下,“用戶名已被占用”。
另一個例子是:
.andExpect(jsonPath("$").value(containsString("You have successfully deleted")));
身體反應:
Body = You have successfully deleted a [Object] with ID: 1
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.