diff --git a/spring-test/src/main/java/org/springframework/test/web/servlet/request/MockMultipartHttpServletRequestBuilder.java b/spring-test/src/main/java/org/springframework/test/web/servlet/request/MockMultipartHttpServletRequestBuilder.java index b6aa5cb0e3b..e176a798f64 100644 --- a/spring-test/src/main/java/org/springframework/test/web/servlet/request/MockMultipartHttpServletRequestBuilder.java +++ b/spring-test/src/main/java/org/springframework/test/web/servlet/request/MockMultipartHttpServletRequestBuilder.java @@ -67,6 +67,11 @@ public class MockMultipartHttpServletRequestBuilder extends MockHttpServletReque this(HttpMethod.POST, urlTemplate, uriVariables); } + /** + * Variant of {@link #MockMultipartHttpServletRequestBuilder(String, Object...)} + * that also accepts an {@link HttpMethod}. + * @since 5.3.22 + */ MockMultipartHttpServletRequestBuilder(HttpMethod httpMethod, String urlTemplate, Object... uriVariables) { super(httpMethod, urlTemplate, uriVariables); super.contentType(MediaType.MULTIPART_FORM_DATA); diff --git a/spring-test/src/main/java/org/springframework/test/web/servlet/request/MockMvcRequestBuilders.java b/spring-test/src/main/java/org/springframework/test/web/servlet/request/MockMvcRequestBuilders.java index 94d78b5b20c..bb8356a3065 100644 --- a/spring-test/src/main/java/org/springframework/test/web/servlet/request/MockMvcRequestBuilders.java +++ b/spring-test/src/main/java/org/springframework/test/web/servlet/request/MockMvcRequestBuilders.java @@ -205,7 +205,8 @@ public abstract class MockMvcRequestBuilders { } /** - * Create a {@link MockMultipartHttpServletRequestBuilder} for a multipart request. + * Create a {@link MockMultipartHttpServletRequestBuilder} for a multipart request, + * using POST as the HTTP method. * @param urlTemplate a URL template; the resulting URL will be encoded * @param uriVars zero or more URI variables * @since 5.0 @@ -215,7 +216,8 @@ public abstract class MockMvcRequestBuilders { } /** - * Create a {@link MockMultipartHttpServletRequestBuilder} for a multipart request. + * Variant of {@link #multipart(String, Object...)} that also accepts an + * {@link HttpMethod}. * @param httpMethod the HTTP method to use * @param urlTemplate a URL template; the resulting URL will be encoded * @param uriVars zero or more URI variables diff --git a/spring-test/src/test/java/org/springframework/test/web/servlet/samples/standalone/MultipartControllerTests.java b/spring-test/src/test/java/org/springframework/test/web/servlet/samples/standalone/MultipartControllerTests.java index f525ac79712..03495b20b26 100644 --- a/spring-test/src/test/java/org/springframework/test/web/servlet/samples/standalone/MultipartControllerTests.java +++ b/spring-test/src/test/java/org/springframework/test/web/servlet/samples/standalone/MultipartControllerTests.java @@ -35,6 +35,7 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; +import org.springframework.http.HttpMethod; import org.springframework.mock.web.MockMultipartFile; import org.springframework.mock.web.MockPart; import org.springframework.stereotype.Controller; @@ -45,6 +46,7 @@ import org.springframework.util.StreamUtils; import org.springframework.validation.BindingResult; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RequestPart; import org.springframework.web.filter.OncePerRequestFilter; @@ -61,20 +63,30 @@ import static org.springframework.test.web.servlet.setup.MockMvcBuilders.standal * @author Rossen Stoyanchev * @author Juergen Hoeller * @author Jaebin Joo + * @author Sam Brannen */ public class MultipartControllerTests { @ParameterizedTest - @ValueSource(strings = {"/multipartfile", "/part"}) - public void multipartRequestWithSingleFileOrPart(String url) throws Exception { + @ValueSource(strings = {"/multipartfile", "/multipartfile-via-put", "/part"}) + void multipartRequestWithSingleFileOrPart(String url) throws Exception { byte[] fileContent = "bar".getBytes(StandardCharsets.UTF_8); byte[] json = "{\"name\":\"yeeeah\"}".getBytes(StandardCharsets.UTF_8); MockMultipartFile jsonPart = new MockMultipartFile("json", "json", "application/json", json); - MockMultipartHttpServletRequestBuilder requestBuilder = (url.endsWith("file") ? - multipart(url).file(new MockMultipartFile("file", "orig", null, fileContent)) : - multipart(url).part(new MockPart("part", "orig", fileContent))); + MockMultipartHttpServletRequestBuilder requestBuilder; + switch (url) { + case "/multipartfile": + requestBuilder = multipart(url).file(new MockMultipartFile("file", "orig", null, fileContent)); + break; + case "/multipartfile-via-put": + requestBuilder = multipart(HttpMethod.PUT, url).file(new MockMultipartFile("file", "orig", null, fileContent)); + break; + default: + requestBuilder = multipart(url).part(new MockPart("part", "orig", fileContent)); + break; + } standaloneSetup(new MultipartController()).build() .perform(requestBuilder.file(jsonPart)) @@ -275,6 +287,13 @@ public class MultipartControllerTests { } @RequestMapping(value = "/multipartfilearray", method = RequestMethod.POST) + @PutMapping("/multipartfile-via-put") + public String processMultipartFileViaHttpPut(@RequestParam(required = false) MultipartFile file, + @RequestPart(required = false) Map json, Model model) throws IOException { + + return processMultipartFile(file, json, model); + } + public String processMultipartFileArray(@RequestParam(required = false) MultipartFile[] file, @RequestPart(required = false) Map json, Model model) throws IOException {