Using Spring MVC Test to unit test multipart POST request Using Spring MVC Test to unit test multipart POST request spring spring

Using Spring MVC Test to unit test multipart POST request


Since MockMvcRequestBuilders#fileUpload is deprecated, you'll want to use MockMvcRequestBuilders#multipart(String, Object...) which returns a MockMultipartHttpServletRequestBuilder. Then chain a bunch of file(MockMultipartFile) calls.

Here's a working example. Given a @Controller

@Controllerpublic class NewController {    @RequestMapping(value = "/upload", method = RequestMethod.POST)    @ResponseBody    public String saveAuto(            @RequestPart(value = "json") JsonPojo pojo,            @RequestParam(value = "some-random") String random,            @RequestParam(value = "data", required = false) List<MultipartFile> files) {        System.out.println(random);        System.out.println(pojo.getJson());        for (MultipartFile file : files) {            System.out.println(file.getOriginalFilename());        }        return "success";    }    static class JsonPojo {        private String json;        public String getJson() {            return json;        }        public void setJson(String json) {            this.json = json;        }    }}

and a unit test

@WebAppConfiguration@ContextConfiguration(classes = WebConfig.class)@RunWith(SpringJUnit4ClassRunner.class)public class Example {    @Autowired    private WebApplicationContext webApplicationContext;    @Test    public void test() throws Exception {        MockMultipartFile firstFile = new MockMultipartFile("data", "filename.txt", "text/plain", "some xml".getBytes());        MockMultipartFile secondFile = new MockMultipartFile("data", "other-file-name.data", "text/plain", "some other type".getBytes());        MockMultipartFile jsonFile = new MockMultipartFile("json", "", "application/json", "{\"json\": \"someValue\"}".getBytes());        MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();        mockMvc.perform(MockMvcRequestBuilders.multipart("/upload")                        .file(firstFile)                        .file(secondFile)                        .file(jsonFile)                        .param("some-random", "4"))                    .andExpect(status().is(200))                    .andExpect(content().string("success"));    }}

And the @Configuration class

@Configuration@ComponentScan({ "test.controllers" })@EnableWebMvcpublic class WebConfig extends WebMvcConfigurationSupport {    @Bean    public MultipartResolver multipartResolver() {        CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver();        return multipartResolver;    }}

The test should pass and give you output of

4 // from paramsomeValue // from json filefilename.txt // from first fileother-file-name.data // from second file

The thing to note is that you are sending the JSON just like any other multipart file, except with a different content type.


The method MockMvcRequestBuilders.fileUpload is deprecated use MockMvcRequestBuilders.multipart instead.

This is an example:

import static org.hamcrest.CoreMatchers.containsString;import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;import org.junit.Before;import org.junit.Test;import org.junit.runner.RunWith;import org.mockito.Mockito;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;import org.springframework.boot.test.mock.mockito.MockBean;import org.springframework.mock.web.MockMultipartFile;import org.springframework.test.context.junit4.SpringRunner;import org.springframework.test.web.servlet.MockMvc;import org.springframework.test.web.servlet.ResultActions;import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;import org.springframework.test.web.servlet.result.MockMvcResultHandlers;import org.springframework.test.web.servlet.setup.MockMvcBuilders;import org.springframework.web.context.WebApplicationContext;import org.springframework.web.multipart.MultipartFile;/** * Unit test New Controller. * */@RunWith(SpringRunner.class)@WebMvcTest(NewController.class)public class NewControllerTest {    private MockMvc mockMvc;    @Autowired    WebApplicationContext wContext;    @MockBean    private NewController newController;    @Before    public void setup() {        this.mockMvc = MockMvcBuilders.webAppContextSetup(wContext)                   .alwaysDo(MockMvcResultHandlers.print())                   .build();    }   @Test    public void test() throws Exception {       // Mock Request        MockMultipartFile jsonFile = new MockMultipartFile("test.json", "", "application/json", "{\"key1\": \"value1\"}".getBytes());        // Mock Response        NewControllerResponseDto response = new NewControllerDto();        Mockito.when(newController.postV1(Mockito.any(Integer.class), Mockito.any(MultipartFile.class))).thenReturn(response);        mockMvc.perform(MockMvcRequestBuilders.multipart("/fileUpload")                .file("file", jsonFile.getBytes())                .characterEncoding("UTF-8"))        .andExpect(status().isOk());    }}


Have a look at this example taken from the spring MVC showcase, this is the link to the source code:

@RunWith(SpringJUnit4ClassRunner.class)public class FileUploadControllerTests extends AbstractContextControllerTests {    @Test    public void readString() throws Exception {        MockMultipartFile file = new MockMultipartFile("file", "orig", null, "bar".getBytes());        webAppContextSetup(this.wac).build()            .perform(fileUpload("/fileupload").file(file))            .andExpect(model().attribute("message", "File 'orig' uploaded successfully"));    }}