Cómo verificar la cadena en el cuerpo de la respuesta con mockMvc
Tengo una prueba de integración simple.
@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(?);
}
En la última línea quiero comparar la cadena recibida en el cuerpo de la respuesta con la cadena esperada.
Y en respuesta me sale:
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
Probé algunos trucos con content(), body() pero nada funcionó.
Puede llamar andReturn()
y utilizar el MvcResult
objeto devuelto para obtener el contenido como archivo String
.
Vea abajo:
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
La respuesta de @Sotirios Delimanolis hace el trabajo, sin embargo, estaba buscando comparar cadenas dentro de esta afirmación simulada de Mvc.
Asi que aqui esta
.andExpect(content().string("\"Username already taken - please try with different username\""));
Por supuesto, mi afirmación falla:
java.lang.AssertionError: Response content expected:
<"Username already taken - please try with different username"> but was:<"Something gone wrong">
porque:
MockHttpServletResponse:
Body = "Something gone wrong"
¡Así que esta es la prueba de que funciona!
Spring MockMvc ahora tiene soporte directo para JSON. Entonces solo dices:
.andExpect(content().json("{'message':'ok'}"));
y a diferencia de la comparación de cadenas, dirá algo como "campo faltante xyz" o "mensaje esperado 'ok' recibido 'nok'.
Este método se introdujo en Spring 4.1.
Al leer estas respuestas, puedo ver muchas cosas relacionadas con la versión 4.x de Spring. Estoy usando la versión 3.2.0 por varias razones. Por lo tanto, cosas como la compatibilidad con json directamente desde el content()
no son posibles.
Descubrí que usarlo MockMvcResultMatchers.jsonPath
es realmente fácil y funciona de maravilla. A continuación se muestra un ejemplo que prueba un método de publicación.
La ventaja de esta solución es que todavía estás haciendo coincidir los atributos, sin depender de comparaciones completas de cadenas json.
(Usando 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));
El cuerpo de la solicitud era solo una cadena json, que puede cargar fácilmente desde un archivo de datos simulado json real si lo desea, pero no lo incluí aquí porque se habría desviado de la pregunta.
El json real devuelto se habría visto así:
{
"data":"some value"
}
Tomado del tutorial de primavera.
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
está disponible desdeimport static org.hamcrest.Matchers.*;
jsonPath
está disponible desdeimport static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
y jsonPath
la referencia se puede encontrar aquí