Модульное тестирование с использованием MockMultipartHttpServletRequest (генерирует исключение NullPointerException в ItemInputStream.makeAvailable) - PullRequest
7 голосов
/ 28 февраля 2012

Я написал класс преобразователя, который принимает HttpServletRequest и преобразует его в другой тип, который содержит указатель на InputStream из запроса сервлета. (Идея состоит в том, чтобы абстрагировать входящий транспортный протокол от обработки запросов, чтобы я мог, например, написать аналогичный преобразователь из FTP.)

Сейчас я пытаюсь написать модульный тест для этого, и у меня проблемы. Мне удалось выяснить правильный шаблон для создания правильного многочастного HTTP-запроса (используя классы Spring MockMultipartHttpServletRequest и MockMultipartFile), но теперь я получаю исключение NullPointerException в методе initialize() моего класса UploadRequest. Я предполагаю, что проблема в том, что каким-то образом поток внутри 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.<init>(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<String, String> params;
  private InputStream strIn;
  private Logger Log = Logger.getLogger(UploadRequest.class.getName());

  public UploadRequest()
  {
    params = new HashMap<String, String>();
  }

  public void initialize(HttpServletRequest sRequest, 
                         ServletFileUpload upload)
    throws IOException, FileUploadException
  {
    Enumeration<String> 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;
      }
    }
  }

А вот и юнит-тест:

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

Ответы [ 3 ]

1 голос
/ 08 февраля 2013
  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);
    

Функция кодирования текста

    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();
    }
1 голос
/ 30 мая 2015

Я прошел через ту же проблему, после поиска лота, я получил это сообщение, в котором я ответил с кодом, который решил мою проблему.

Решение Шрипрасада хорошо работает для текстового файла. Но у меня были некоторые проблемы с бинарными файлами.

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

1 голос
/ 05 апреля 2012

У меня та же проблема, и я погуглил, но ответа нет.Я подключил исходный код из библиотеки, Вам нужно отправить контент, что угодно.Библиотеке, возможно, потребуется проверить, имеет ли она значение null, в методе пропуска

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

Опубликовано здесь для других

...