Sử dụng Spring MVC Test để kiểm tra đơn vị yêu cầu POST


115

Tôi có trình xử lý yêu cầu sau để lưu ô tô. Tôi đã xác minh rằng điều này hoạt động khi tôi sử dụng ví dụ: cURL. Bây giờ tôi muốn kiểm tra đơn vị phương pháp với Kiểm tra MVC mùa xuân. Tôi đã cố gắng sử dụng fileUploader, nhưng tôi không quản lý được để nó hoạt động. Tôi cũng không quản lý để thêm phần JSON.

Làm cách nào để kiểm tra đơn vị phương pháp này với Spring MVC Test? Tôi không thể tìm thấy bất kỳ ví dụ nào về điều này.

@RequestMapping(value = "autos", method = RequestMethod.POST)
public ResponseEntity saveAuto(
    @RequestPart(value = "data") autoResource,
    @RequestParam(value = "files[]", required = false) List<MultipartFile> files) {
    // ...
}

Tôi muốn nâng cấp đại diện JSON cho tự động + một hoặc nhiều tệp của mình.

Tôi sẽ thêm 100 tiền thưởng vào câu trả lời đúng!

Câu trả lời:


256

MockMvcRequestBuilders#fileUploadkhông được dùng nữa, bạn sẽ muốn sử dụng MockMvcRequestBuilders#multipart(String, Object...)trả về a MockMultipartHttpServletRequestBuilder. Sau đó, chuỗi một loạt các file(MockMultipartFile)cuộc gọi.

Đây là một ví dụ hoạt động. Đưa ra@Controller

@Controller
public 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;
        }

    }
}

và một bài kiểm tra đơn vị

@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"));
    }
}

@Configurationlớp học

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

Bài kiểm tra sẽ vượt qua và cung cấp cho bạn kết quả

4 // from param
someValue // from json file
filename.txt // from first file
other-file-name.data // from second file

Điều cần lưu ý là bạn đang gửi JSON giống như bất kỳ tệp đa phần nào khác, ngoại trừ với một loại nội dung khác.


1
Xin chào Sotirios, tôi rất vui khi thấy tấm gương đẹp đó, và sau đó tôi tìm xem ai là người đã đưa ra nó, và chơi lô tô! Đó là Sotirios! Thử nghiệm làm cho nó thực sự tuyệt vời. Tuy nhiên, tôi có một điều khiến tôi khó chịu, nó phàn nàn rằng yêu cầu không phải là một yêu cầu nhiều phần (500).
Stephane

Đó là khẳng định này không thành công khẳng định IsMultipartRequest (servletRequest); Tôi nghi ngờ CommonsMultipartResolver không được định cấu hình. Nhưng một bản ghi trong bean của tôi được hiển thị trong bản ghi.
Stephane

@shredding Tôi đã thực hiện cách tiếp cận này trong việc gửi tệp nhiều phần và đối tượng mô hình dưới dạng json tới bộ điều khiển của mình. Nhưng đối tượng mô hình ném MethodArgumentConversionNotSupportedExceptionkhi chạm vào bộ điều khiển..bất kỳ bước nào tôi đã bỏ lỡ ở đây? - stackoverflow.com/questions/50953227/…
Brian J

1
Ví dụ này đã giúp tôi rất nhiều. Cảm ơn
kiranNswamy

đa phần sử dụng phương thức POST. Ai có thể cung cấp cho tôi ví dụ này nhưng với phương pháp PATCH?
lalilulelo_1986

16

Hãy xem ví dụ này được lấy từ buổi giới thiệu MVC mùa xuân, đây là liên kết đến mã nguồn :

@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"));
    }

}

1
fileUploadkhông được ủng hộ multipart(String, Object...).
naXa

14

Thay vào đó, phương pháp MockMvcRequestBuilders.fileUploadnày không được dùng nữa MockMvcRequestBuilders.multipart.

Đây là một ví dụ:

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());

    }

}

2

Đây là những gì phù hợp với tôi, đây là tôi đang đính kèm một tệp vào EmailController của tôi đang được thử nghiệm. Ngoài ra, hãy xem ảnh chụp màn hình của người đưa thư về cách tôi đăng dữ liệu.

    @WebAppConfiguration
    @RunWith(SpringRunner.class)
    @SpringBootTest(
            classes = EmailControllerBootApplication.class
        )
    public class SendEmailTest {

        @Autowired
        private WebApplicationContext webApplicationContext;

        @Test
        public void testSend() throws Exception{
            String jsonStr = "{\"to\": [\"email.address@domain.com\"],\"subject\": "
                    + "\"CDM - Spring Boot email service with attachment\","
                    + "\"body\": \"Email body will contain  test results, with screenshot\"}";

            Resource fileResource = new ClassPathResource(
                    "screen-shots/HomePage-attachment.png");

            assertNotNull(fileResource);

            MockMultipartFile firstFile = new MockMultipartFile( 
                       "attachments",fileResource.getFilename(),
                        MediaType.MULTIPART_FORM_DATA_VALUE,
                        fileResource.getInputStream());  
                        assertNotNull(firstFile);


            MockMvc mockMvc = MockMvcBuilders.
                  webAppContextSetup(webApplicationContext).build();

            mockMvc.perform(MockMvcRequestBuilders
                   .multipart("/api/v1/email/send")
                    .file(firstFile)
                    .param("data", jsonStr))
                    .andExpect(status().is(200));
            }
        }

Yêu cầu người đưa thư


Cảm ơn bạn rất nhiều câu trả lời của bạn cũng phù hợp với tôi @Alfred
Parameshwar

1

Nếu bạn đang sử dụng Spring4 / SpringBoot 1.x, thì điều đáng nói là bạn cũng có thể thêm các phần "văn bản" (json). Điều này có thể được thực hiện thông qua tệp MockMvcRequestBuilders.fileUpload (). (Tệp MockMultipartFile) (cần thiết vì phương pháp .multipart()này không khả dụng trong phiên bản này):

@Test
public void test() throws Exception {

   mockMvc.perform( 
       MockMvcRequestBuilders.fileUpload("/files")
         // file-part
         .file(makeMultipartFile( "file-part" "some/path/to/file.bin", "application/octet-stream"))
        // text part
         .file(makeMultipartTextPart("json-part", "{ \"foo\" : \"bar\" }", "application/json"))
       .andExpect(status().isOk())));

   }

   private MockMultipartFile(String requestPartName, String filename, 
       String contentType, String pathOnClassPath) {

       return new MockMultipartFile(requestPartName, filename, 
          contentType, readResourceFile(pathOnClasspath);
   }

   // make text-part using MockMultipartFile
   private MockMultipartFile makeMultipartTextPart(String requestPartName, 
       String value, String contentType) throws Exception {

       return new MockMultipartFile(requestPartName, "", contentType,
               value.getBytes(Charset.forName("UTF-8")));   
   }


   private byte[] readResourceFile(String pathOnClassPath) throws Exception {
      return Files.readAllBytes(Paths.get(Thread.currentThread().getContextClassLoader()
         .getResource(pathOnClassPath).toUri()));
   }

}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.