如何使用MockMVC测试使用org.apache.commons.fileupload的控制器?

时间:2019-11-27 07:55:10

标签: spring-boot file-upload mockmvc

我的控制器使用“ org.apache.commons.fileupload”实现了文件UPload。 看到它:

 @PostMapping("/upload")
    public String upload2(HttpServletRequest request) throws Exception {

        ServletFileUpload upload = new ServletFileUpload();
        FileItemIterator iter = upload.getItemIterator(request);
        boolean uploaded = false;

        while (iter.hasNext() && !uploaded) {
            FileItemStream item = iter.next();
            if (item.isFormField()) {
                item.openStream().close();
            } else {
                String fieldName = item.getFieldName();
                if (!"file".equals(fieldName)) {
                    item.openStream().close();
                } else {

                    InputStream stream = item.openStream();
                    // dosomething here.
                    uploaded = true;
                }
            }
        }
            if (uploaded) {
                return "ok";
            } else {
                throw new BaseResponseException(HttpStatus.BAD_REQUEST, "400", "no file field or data file is empty.");
            }

        }

我的MockMvc代码是

    public void upload() throws Exception {
        File file = new File("/Users/jianxiaowen/Documents/a.txt");
        MockMultipartFile multipartFile = new MockMultipartFile("file", new FileInputStream(file));
        HashMap<String, String> contentTypeParams = new HashMap<String, String>();
        contentTypeParams.put("boundary", "----WebKitFormBoundaryaDEFKSFMY18ehkjt");
        MediaType mediaType = new MediaType("multipart", "form-data", contentTypeParams);
        MvcResult mvcResult = mockMvc.perform(MockMvcRequestBuilders.post(baseUrl+"/upload")
                .content(multipartFile.getBytes())
                .contentType(mediaType)
                .header(Origin,OriginValue)
                .cookie(cookie))
                .andReturn();
        logResult(mvcResult);
    }

我的控制器是正确的,它已经在我的Web项目中成功完成, 但我想使用MvcMock对其进行测试,它有一些错误,请参见:  有人可以帮我吗?

"status":"400","msg":"no file field or data file is empty.","data":null

我不知道为什么它说我的文件为空。 我的英语很差,如果有人可以帮助我,非常感谢。

2 个答案:

答案 0 :(得分:1)

您可以尝试以下吗?

mockMvc.perform(
  MockMvcRequestBuilders.multipart(baseUrl+"/upload")
    .file(multiPartFile)
).andReturn();

更新:

您需要更新控制器以处理MultipartFile

@PostMapping("/upload")
public String upload2(@RequestParam(name="nameOfRequestParamWhichContainsFileData")
     MultipartFile uploadedFile, HttpServletRequest request) throws Exception {
  //the uploaded file gets copied to uploadedFile object. 
}

您无需使用其他库来管理文件上传。您可以使用Spring MVC提供的文件上传功能。

答案 1 :(得分:0)

MockMvc 也可用于对使用 Apache Commons Fileupload 的控制器进行集成测试!

  1. org.apache.httpcomponents:httpmime 导入您的 pom.xmlgradle.properties

    <dependency>
       <groupId>org.apache.httpcomponents</groupId>
       <artifactId>httpmime</artifactId>
       <version>4.5.13</version>
    </dependency>
    
  2. 更新代码使用MultipartEntityBuilder在客户端构建multipart请求,然后将实体序列化为bytes,然后在请求内容中设置

    public void upload() throws Exception {
        File file = new File("/Users/jianxiaowen/Documents/a.txt");
    
        String boundary = "----WebKitFormBoundaryaDEFKSFMY18ehkjt";
    
        // create 'Content-Type' header for multipart along with boundary
        HashMap<String, String> contentTypeParams = new HashMap<String, String>();
        contentTypeParams.put("boundary", boundary); // set boundary in the header
        MediaType mediaType = new MediaType("multipart", "form-data", contentTypeParams);
    
        // create a multipart entity builder, and add parts (file/form data)
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        HttpEntity multipartEntity = MultipartEntityBuilder.create()
            .addPart("file", new FileBody(file, ContentType.create("text/plain"), file.getName())) // add file
            // .addTextBody("param1", "value1") // optionally add form data
            .setBoundary(boundary) // set boundary to be used
            .build();
        multipartEntity.writeTo(outputStream); // or getContent() to get content stream
        byte[] content = outputStream.toByteArray(); // serialize the content to bytes
    
        MvcResult mvcResult = mockMvc.perform(
            MockMvcRequestBuilders.post(baseUrl + "/upload")
                .contentType(mediaType)
                .content(content) // finally set the content
                .header(Origin,OriginValue)
                .cookie(cookie)
            ).andReturn();
        logResult(mvcResult);
    }