स्प्रिंग एमवीसी टेस्ट टू यूनिट टेस्ट का उपयोग POST अनुरोध को मल्टीपार्ट करें


115

मेरे पास ऑटोस को बचाने के लिए निम्नलिखित अनुरोध हैंडलर है। मैंने सत्यापित किया है कि जब मैं उदाहरण cURL का उपयोग करता हूं तो यह काम करता है। अब मैं स्प्रिंग एमवीसी टेस्ट के साथ विधि का परीक्षण करना चाहता हूं। मैंने फ़ाइलअपलोडर का उपयोग करने की कोशिश की है, लेकिन मैं इसे काम करने के लिए प्रबंधित नहीं कर रहा हूं। न ही मैं JSON भाग जोड़ने का प्रबंधन करता हूं।

मैं स्प्रिंग एमवीसी टेस्ट के साथ इस विधि का परीक्षण कैसे करूंगा? मुझे इस पर कोई उदाहरण नहीं मिल रहा है।

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

मैं अपने ऑटो + एक या अधिक फ़ाइलों के लिए JSON प्रतिनिधित्व को अपलोड़ करना चाहता हूं।

मैं सही उत्तर के लिए इनाम में 100 जोड़ूंगा!

जवाबों:


256

जब MockMvcRequestBuilders#fileUploadसे पदावनत किया गया है, आप का उपयोग करना चाहते हैं MockMvcRequestBuilders#multipart(String, Object...)जो एक रिटर्न देता है MockMultipartHttpServletRequestBuilder। फिर file(MockMultipartFile)कॉल का एक गुच्छा श्रृंखला ।

यहाँ एक कार्यशील उदाहरण है। दिया गया@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;
        }

    }
}

और एक इकाई परीक्षण

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

और @Configurationवर्ग

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

परीक्षण पास होना चाहिए और आपको आउटपुट देना चाहिए

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

ध्यान देने वाली बात यह है कि आप JSON को किसी भी अन्य मल्टीपार्ट फाइल की तरह ही भेज रहे हैं, एक अलग सामग्री प्रकार के अलावा।


1
हाय Sotirios, मैं उस सुंदर उदाहरण को देखकर खुश था, और फिर मैंने देखा कि यह कौन था जिसने इसे पेश किया, और बिंगो! यह Sotirios था! परीक्षण वास्तव में अच्छा बनाता है। मेरे पास एक चीज है जो मुझे परेशान कर रही है, हालांकि, यह शिकायत करता है कि अनुरोध एक मल्टीपार्ट एक (500) नहीं है।
स्टीफन

यह मुखरता है कि assertIsMultipartRequest (सर्वलेट) को विफल करता है; मुझे संदेह था कि CommonsMultipartResolver कॉन्फ़िगर नहीं किया गया था। लेकिन मेरे बीन में एक लकड़हारा लॉग में प्रदर्शित होता है।
स्टीफन

@shredding मैंने अपने कंट्रोलर को एक मल्टीपार्ट फाइल और एक मॉडल ऑब्जेक्ट को json के रूप में भेजने में लिया। लेकिन मॉडल ऑब्जेक्ट फेंकता हैMethodArgumentConversionNotSupportedException नियंत्रक को मारते समय सूक्ष्म कदम जो मैंने यहां याद किया है? - stackoverflow.com/questions/50953227/…
ब्रायन जे

1
इस उदाहरण से मुझे बहुत मदद मिली। धन्यवाद
kiranNswamy

मल्टीपार्ट POST विधि का उपयोग करता है। किसी ने मुझे इस उदाहरण प्रदान कर सकते हैं लेकिन पैट विधि के साथ?
lalilulelo_1986

16

स्प्रिंग एमवीसी शोकेस से लिए गए इस उदाहरण पर एक नज़र डालें, यह स्रोत कोड की लिंक है :

@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
fileUploadके पक्ष में पदावनत किया जाता है multipart(String, Object...)
17

14

इसके बजाय विधि MockMvcRequestBuilders.fileUploadका उपयोग किया MockMvcRequestBuilders.multipartजाता है।

यह एक उदाहरण है:

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

यहाँ मेरे लिए क्या काम किया गया है, यहाँ मैं एक फ़ाइल को परीक्षण के तहत अपने EmailController को संलग्न कर रहा हूँ। इसके अलावा पोस्टमैन स्क्रीनशॉट पर एक नज़र डालें कि मैं डेटा कैसे पोस्ट कर रहा हूं।

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

डाकिया अनुरोध


बहुत बहुत धन्यवाद आपका जवाब मेरे लिए भी काम किया @Alfred
Parameshwar

1

यदि आप स्प्रिंग 4 / स्प्रिंगबूट 1.x का उपयोग कर रहे हैं, तो यह ध्यान देने योग्य है कि आप "टेक्स्ट" (json) भागों को भी जोड़ सकते हैं। यह MockMvcRequestBuilders.fileUpload () फ़ाइल के माध्यम से किया जा सकता है (MockMultipartFile फ़ाइल) (जो .multipart()इस संस्करण में विधि उपलब्ध नहीं है) की आवश्यकता है:

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

}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.