J'ai un test d'intégration 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 dernière ligne, je souhaite comparer la chaîne reçue dans le corps de la réponse à la chaîne attendue
Et en réponse je reçois:
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
J'ai essayé quelques astuces avec content (), body () mais rien n'a fonctionné.
La réponse de @Sotirios Delimanolis fait le travail mais je cherchais des chaînes de comparaison dans cette affirmation fictive
Alors voila
.andExpect(content().string("\"Username already taken - please try with different username\""));
Bien sûr, mon assertion échoue:
Java.lang.AssertionError: Response content expected:
<"Username already taken - please try with different username"> but was:<"Something gone wrong">
parce que:
MockHttpServletResponse:
Body = "Something gone wrong"
Donc, c'est la preuve que ça marche!
Vous pouvez appeler andReturn()
et utiliser l'objet MvcResult
renvoyé pour obtenir le contenu sous forme de String
.
Voir ci-dessous:
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
Spring MockMvc prend désormais en charge directement JSON. Alors vous dites juste:
.andExpect(content().json("{'message':'ok'}"));
et contrairement à la comparaison de chaînes, il va dire quelque chose comme "champ manquant xyz" ou "message attendu" ok "obtenu" nok ".
Cette méthode a été introduite au printemps 4.1.
En lisant ces réponses, je vois beaucoup de choses sur Spring version 4.x. J'utilise la version 3.2.0 pour diverses raisons. Donc, des choses comme le support json directement à partir de la content()
ne sont pas possibles.
J'ai trouvé que l'utilisation de MockMvcResultMatchers.jsonPath
est très simple et fonctionne très bien. Voici un exemple de test d'une méthode de publication.
L'avantage de cette solution est que vous faites toujours correspondre les attributs, sans vous fier aux comparaisons complètes de chaînes JSON.
(Utilisation de 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));
Le corps de la demande était juste une chaîne json, que vous pouvez facilement charger à partir d’un fichier de données simulé si vous le vouliez, mais je n’ai pas inclus cela ici car cela aurait dévié de la question.
Le JSON retourné aurait ressemblé à ceci:
{
"data":"some value"
}
Le @WithMockUser
de Spring Security et le matcher containsString
de hamcrest constituent une solution simple et élégante:
@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.")));
}
Tiré du printemps tutoriel
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 à partir de import static org.hamcrest.Matchers.*;
jsonPath
est disponible à partir de import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
et jsonPath
référence peut être trouvé ici
voici une manière plus élégante
mockMvc.perform(post("/retrieve?page=1&countReg=999999")
.header("Authorization", "Bearer " + validToken))
.andExpect(status().isOk())
.andExpect(content().string(containsString("regCount")));
String body = mockMvc.perform(bla... bla).andReturn().getResolvedException().getMessage()
Cela devrait vous donner le corps de la réponse. "Nom d'utilisateur déjà pris" dans votre cas.
Voici un exemple comment analyser une réponse JSON et même comment envoyer une demande avec un bean au format JSON:
@Autowired
protected MockMvc mvc;
private static final ObjectMapper MAPPER = new ObjectMapper()
.configure(WRITE_DATES_AS_TIMESTAMPS, false)
.configure(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());
}
Comme vous pouvez le voir ici, la Book
est une requête DTO et la UpdateBookResponse
un objet de réponse analysé à partir de JSON. Vous voudrez peut-être changer la configuration de Jakson ObjectMapper
.