J'écris des tests pour vérifier que je peux faire un post de formulaire générique sur notre API.
J'ai également ajouté un certain débogage, mais j'ai remarqué que les données publiées par un formulaire réel; (Postman/AngularJS ou w/e) Diffère de faire un test mockMVC comme:
MvcResult response = mockMvc
.perform(post("/some/super/secret/url") //
.param("someparam1", "somevalue") //
.param("someparam2", "somevalue") //
.contentType(MediaType.APPLICATION_FORM_URLENCODED) //
.accept(MediaType.APPLICATION_JSON)) //
.andExpect(status().isOk()) //
.andReturn();
La configuration est exactement la même que la configuration en cours de production, etc. Cependant, lorsque mon intercepteur enregistre le contenu, dans un test réel (pas mockMVC), le contenu est formaté comme "someparam1 = somevalue & etc = encore"
Lorsque j'imprime le contenu mockMVC, il semble que je n'ai aucun contenu, mais il y a des paramètres dans la demande, je suppose qu'ils sont ajoutés comme des paramètres GET.
Quelqu'un sait comment tester correctement cela? Je suis tombé sur ce problème car il semble que nos publications de formulaire ne semblent pas être analysées par Spring, même si le FormHttpMessageConverter a été ajouté au contexte de servlet.
Si vous avez Apache HTTPComponents HttpClient sur votre chemin de classe, vous pouvez le faire comme ceci:
mockMvc.perform(post("/some/super/secret/url")
.contentType(MediaType.APPLICATION_FORM_URLENCODED)
.content(EntityUtils.toString(new UrlEncodedFormEntity(Arrays.asList(
new BasicNameValuePair("someparam1", "true"),
new BasicNameValuePair("someparam2", "test")
)))));
Si vous n'avez pas HttpClient, vous pouvez le faire avec une méthode d'assistance simple qui construit l'entité de formulaire urlencoded:
mockMvc.perform(post("/some/super/secret/url")
.contentType(MediaType.APPLICATION_FORM_URLENCODED)
.content(buildUrlEncodedFormEntity(
"someparam1", "value1",
"someparam2", "value2"
))));
Avec cette fonction d'assistance:
private String buildUrlEncodedFormEntity(String... params) {
if( (params.length % 2) > 0 ) {
throw new IllegalArgumentException("Need to give an even number of parameters");
}
StringBuilder result = new StringBuilder();
for (int i=0; i<params.length; i+=2) {
if( i > 0 ) {
result.append('&');
}
try {
result.
append(URLEncoder.encode(params[i], StandardCharsets.UTF_8.name())).
append('=').
append(URLEncoder.encode(params[i+1], StandardCharsets.UTF_8.name()));
}
catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
}
return result.toString();
}
Vous pouvez également utiliser cette petite bibliothèque que j'ai créée: https://github.com/f-lopes/spring-mvc-test-utils/ .
Ajoutez une dépendance dans pom.xml:
<dependency>
<groupId>io.florianlopes</groupId>
<artifactId>spring-mvc-test-utils</artifactId>
<version>1.0.1</version>
<scope>test</scope>
</dependency>
Utilisez-le avec MockMvc:
mockMvc.perform(MockMvcRequestBuilderUtils.postForm("/users", new AddUserForm("John", "Doe", null, new Address(1, "Street", 5222, "New York"))))
.andExpect(MockMvcResultMatchers.status().isFound())
.andExpect(MockMvcResultMatchers.redirectedUrl("/users"))
.andExpect(MockMvcResultMatchers.flash().attribute("message", "success"));
Cette bibliothèque ajoute simplement les paramètres à la demande MockMvc, selon l'objet de formulaire.
Voici un tutoriel détaillé que j'ai écrit: https://blog.florianlopes.io/tool-for-spring-mockmvcrequestbuilder-forms-tests/