J'ai une méthode de contrôleur avec une méthode PUT
, qui reçoit des données multipart/form:
@RequestMapping(value = "/putIn", method = RequestMethod.PUT)
public Foo updateFoo(HttpServletRequest request,
@RequestBody Foo foo,
@RequestParam("foo_icon") MultipartFile file) {
...
}
et je veux le tester en utilisant MockMvc
. Malheureusement MockMvcRequestBuilders.fileUpload
crée essentiellement une instance de MockMultipartHttpServletRequestBuilder
qui a une méthode POST
:
super(HttpMethod.POST, urlTemplate, urlVariables)
MODIFIER: Je peux certainementje ne peux pas créer ma propre implémentation de MockHttpServletRequestBuilder
, disons
public MockPutMultipartHttpServletRequestBuilder(String urlTemplate, Object... urlVariables) {
super(HttpMethod.PUT, urlTemplate, urlVariables);
super.contentType(MediaType.MULTIPART_FORM_DATA);
}
parce que MockHttpServletRequestBuilder
a un constructeur package-local.
Mais je me demande si c'est plus pratique Est-il possible de le faire, est-ce que j'ai raté une classe ou une méthode existante pour le faire?
Oui, il y a un moyen, et c'est simple aussi!
J'ai moi-même rencontré le même problème. Bien que j'étais découragé par la réponse de Sam Brannen, il semble que Spring MVC supporte de nos jours le téléchargement de fichiers PUT car je pouvais simplement faire une telle demande en utilisant Postman (j'utilise Spring Boot 1.4.2). Donc, j'ai continué à creuser et j'ai trouvé que le seul problème était le fait que MockMultipartHttpServletRequestBuilder
renvoyé par MockMvcRequestBuilders.fileUpload()
avait la méthode codée en dur sur "POST". J'ai ensuite découvert la méthode with()
...
et cela m'a permis de trouver cette astuce pour forcer le MockMultipartHttpServletRequestBuilder
à utiliser la méthode "PUT" de toute façon:
MockMultipartFile file = new MockMultipartFile("data", "dummy.csv",
"text/plain", "Some dataset...".getBytes());
MockMultipartHttpServletRequestBuilder builder =
MockMvcRequestBuilders.fileUpload("/test1/datasets/set1");
builder.with(new RequestPostProcessor() {
@Override
public MockHttpServletRequest postProcessRequest(MockHttpServletRequest request) {
request.setMethod("PUT");
return request;
}
});
mvc.perform(builder
.file(file))
.andExpect(status().ok());
Fonctionne comme un charme!
Ceci n'est malheureusement pas actuellement pris en charge dans Spring MVC Test, et je ne vois pas d'autre solution que de créer votre propre MockPutMultipartHttpServletRequestBuilder
et de copier-coller le code personnalisé à partir de l'implémentation standard.
Pour ce que ça vaut, Spring MVC ne prend pas non plus en charge les demandes de téléchargement de fichiers PUT
par défaut. Les résolveurs multiparties sont codés en dur pour accepter uniquement les demandes de téléchargement de fichiers POST
- à la fois pour Apache Commons et la prise en charge de l'API Servlet standard.
Si vous souhaitez que Spring prenne en charge PUT
en plus, n'hésitez pas à ouvrir un ticket dans l'outil de suivi des problèmes JIRA de Spring.
Vous pouvez transmettre à la fois foo
et file
Essayez de réécrire votre contrôleur comme:
@RequestMapping(value = "/putIn", method = RequestMethod.PUT)
public Foo updateFoo(
HttpServletRequest request,
@RequestPart Foo foo,
@RequestPart MultipartFile file) {
...
}
Et le test ressemble à:
MockMultipartFile file = new MockMultipartFile("file", "dummy.csv",
"text/plain", "Some dataset...".getBytes());
// application/json if you pass json as string
MockMultipartFile file2 = new MockMultipartFile("foo", "foo.txt",
"application/json", "Foo data".getBytes());
MockMultipartHttpServletRequestBuilder builder =
MockMvcRequestBuilders.multipart("/test1/datasets/set1");
builder.with(new RequestPostProcessor() {
@Override
public MockHttpServletRequest postProcessRequest(MockHttpServletRequest request) {
request.setMethod("PUT");
return request;
}
});
mvc.perform(builder
.file(file)
.file(file2))
.andExpect(status().ok());