使用MockMultipartHttpServletRequest进行unit testing(在ItemInputStream.makeAvailable中抛出NullPointerException)

我编写了一个带有HttpServletRequest的转换器类,并将其转换为另一种类型,该类型包含一个指向来自servlet请求的InputStream的指针。 (这个想法是从请求处理中抽象出传输传输协议,所以我也可以从FTP编写类似的转换器。)

现在我正在尝试为此编写一个unit testing,我遇到了问题。 我已经设法找出正确的样板来创建有效的Multipart HTTP请求(使用Spring类MockMultipartHttpServletRequest和MockMultipartFile),但现在我在UploadRequest类的initialize()方法中得到NullPointerException。 我猜测问题是,MockMultipartHttpServletRequest内部的流不是正确初始化,但我无法弄清楚我应该做些什么不同。

任何建议都会感激不尽!

这是堆栈跟踪:

 java.lang.NullPointerException at org.apache.commons.fileupload.MultipartStream$ItemInputStream.makeAvailable(MultipartStream.java:976) at org.apache.commons.fileupload.MultipartStream$ItemInputStream.read(MultipartStream.java:886) at java.io.InputStream.read(InputStream.java:82) at org.apache.commons.fileupload.util.Streams.copy(Streams.java:96) at org.apache.commons.fileupload.util.Streams.copy(Streams.java:66) at org.apache.commons.fileupload.MultipartStream.readBodyData(MultipartStream.java:592) at org.apache.commons.fileupload.MultipartStream.discardBodyData(MultipartStream.java:618) at org.apache.commons.fileupload.MultipartStream.skipPreamble(MultipartStream.java:637) at org.apache.commons.fileupload.FileUploadBase$FileItemIteratorImpl.findNextItem(FileUploadBase.java:984) at org.apache.commons.fileupload.FileUploadBase$FileItemIteratorImpl.(FileUploadBase.java:965) at org.apache.commons.fileupload.FileUploadBase.getItemIterator(FileUploadBase.java:331) at org.apache.commons.fileupload.servlet.ServletFileUpload.getItemIterator(ServletFileUpload.java:148) at com.ooyala.UploadRequest.initialize(UploadRequest.java:51) at com.ooyala.UploadRequestTest.testCreateFromServletRequest(UploadRequestTest.java:57) 

这是我的变压器类的缩写版本:

 public class UploadRequest { private Map params; private InputStream strIn; private Logger Log = Logger.getLogger(UploadRequest.class.getName()); public UploadRequest() { params = new HashMap(); } public void initialize(HttpServletRequest sRequest, ServletFileUpload upload) throws IOException, FileUploadException { Enumeration paramNames = sRequest.getParameterNames(); while (paramNames.hasMoreElements()) { String pName = paramNames.nextElement(); params.put(pName, sRequest.getParameter(pName)); } params.put("request_uri", sRequest.getRequestURI()); FileItemIterator iter = upload.getItemIterator(sRequest); while (iter.hasNext()) { FileItemStream item = iter.next(); try { if (!item.isFormField()) { // Skip form fields params.put("original_file_name", item.getName()); strIn = item.openStream(); } } catch (IOException ex) { Log.severe("File uploading exception: " + ex.getMessage()); throw ex; } } } 

这是unit testing:

 import org.springframework.mock.web.MockMultipartHttpServletRequest; import org.springframework.mock.web.MockMultipartFile; import org.apache.commons.fileupload.servlet.ServletFileUpload; // etc.... other imports @RunWith(JMock.class) public class UploadRequestTest { private UploadRequest upRequest; @Before public void setUp() { context.setImposteriser(ClassImposteriser.INSTANCE); upRequest = new UploadRequest(); } @Test public void testCreateFromServletRequest() throws IOException, FileUploadException { String text_contents = "hello world"; MockMultipartHttpServletRequest sRequest = new MockMultipartHttpServletRequest(); sRequest.setMethod("POST"); String boundary = generateBoundary(); String contentType = "multipart/form-data; boundary="+boundary; sRequest.setContentType(contentType); sRequest.setRequestURI("/foo"); sRequest.addParameter("test_param","test_value"); sRequest.addFile( new MockMultipartFile("file1","test_upload.txt","text/plain", text_contents.getBytes())); ServletFileUpload upload = new ServletFileUpload(); assertTrue(upload.isMultipartContent(sRequest)); upRequest.initialize(sRequest, upload); } } 

我有同样的问题,我用谷歌搜索,但没有答案。 我插入了库中的源代码,你需要发送内容,无论如何。 库可能需要检查skip方法中是否为null

 MockMultipartHttpServletRequest request request.setContent("whatever".getBytes()); 

在这里张贴给其他人

  1. 添加边界条件
  2. 生成内容如下

     MockMultipartHttpServletRequest request = this.generateMockMultiPartHttpServletRequest(true); MockMultipartFile mockMultipartFile = null; try { request.setContentType("multipart/form-data; boundary=-----1234"); request.setCharacterEncoding("text/plain"); String endline = "\r\n"; String bondary = "-----1234"; String textFile = this.encodeTextFile("-----1234", "\r\n", "file","test.csv", "text/UTF-8", FileUtils.readFileToString((new File(csvFilePath)), "UTF-8")); StringBuilder content = new StringBuilder(textFile.toString()); content.append(endline); content.append(endline); content.append(endline); content.append("--"); content.append(bondary); content.append("--"); content.append(endline); request.setContent(content.toString().getBytes()); request.setMethod("POST"); mockMultipartFile = new MockMultipartFile("file", FileUtils.readFileToByteArray(new File(csvFilePath))); } catch (Exception e1) { e1.printStackTrace(); } request.addFile(mockMultipartFile); 

编码文本的function

  private String encodeTextFile(String bondary, String endline, String name, String filename, String contentType, String content) { final StringBuilder sb = new StringBuilder(64); sb.append(endline); sb.append("--"); sb.append(bondary); sb.append(endline); sb.append("Content-Disposition: form-data; name=\""); sb.append(name); sb.append("\"; filename=\""); sb.append(filename); sb.append("\""); sb.append(endline); sb.append("Content-Type: "); sb.append(contentType); sb.append(endline); sb.append(endline); sb.append(content); return sb.toString(); } 

我经历了同样的问题,经过搜索很多我得到了这篇post,其中我回答了解决我问题的代码。

Shriprasad的解决方案适用于文本文件。 但我在二进制文件方面遇到了一些问题。

https://stackoverflow.com/a/30541653/2762092