Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Test maximum upload file size with MockMultipartFile

I create a file upload service with Spring Boot and test it with Spring Mock Mvc and MockMultipartFile. I want to test if an error is thrown when the maximum file size is exceeded. The following test fails because it receive a 200.

RandomAccessFile f = new RandomAccessFile("t", "rw");
f.setLength(1024 * 1024 * 10);
InputStream is = Channels.newInputStream(f.getChannel());

MockMultipartFile firstFile = new MockMultipartFile("data", "file1.txt", "text/plain", is);

mvc.perform(fileUpload("/files")
    .file(firstFile))
    .andExpect(status().isInternalServerError());

Is there any possibility to test the upload file size?

like image 378
fabwu Avatar asked Nov 12 '15 08:11

fabwu


2 Answers

You cannot test this with Spring's MockMultipartFile / MockMvc. The reason for this is that the error's origin is not in Spring itself, but in the underlying web server (most often Tomcat), as you can see in the MaxUploadSizeExceededException's stack trace:

org.springframework.web.multipart.MaxUploadSizeExceededException: Maximum upload size of 500000 bytes exceeded; nested exception is org.apache.commons.fileupload.FileUploadBase$SizeLimitExceededException: the request was rejected because its size (1065736) exceeds the configured maximum (500000)
    at org.springframework.web.multipart.commons.CommonsMultipartResolver.parseRequest(CommonsMultipartResolver.java:160)
    at org.springframework.web.multipart.commons.CommonsMultipartResolver.resolveMultipart(CommonsMultipartResolver.java:139)
[...]
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Unknown Source)
Caused by: org.apache.commons.fileupload.FileUploadBase$SizeLimitExceededException: the request was rejected because its size (1065736) exceeds the configured maximum (500000)
    at org.apache.commons.fileupload.FileUploadBase$FileItemIteratorImpl.<init>(FileUploadBase.java:965)
    at org.apache.commons.fileupload.FileUploadBase.getItemIterator(FileUploadBase.java:310)
    at org.apache.commons.fileupload.FileUploadBase.parseRequest(FileUploadBase.java:334)
    at org.apache.commons.fileupload.servlet.ServletFileUpload.parseRequest(ServletFileUpload.java:115)
    at org.springframework.web.multipart.commons.CommonsMultipartResolver.parseRequest(CommonsMultipartResolver.java:156)
    ... 20 more

When using default MockMvc and @SpringBootTest with its default settings, no real web server is started and thus the error does not occur.

You can however tell Spring to start a real web server for your test by supplying @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT), which will (surprise) start a web server on a random port. You can access that port in your test class with @LocalServerPort.

You can then write a test that performs a real multipart upload against your test server and not a faked one. REST Assured is a library, among others, that can do this:

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class MyTest {

    @LocalServerPort
    private int port;

    @Test
    void testMultipartUpload() throws Exception {
        File file = new File("my-file");
        RestAssured.baseURI = "http://localhost/api";
        RestAssured.port = port;
        Response res = given()
                .multiPart("data", file, "text/plain")
                .when().post("/upload");
        ...
    }

}

This test will reveal the server error when your upload is too large.

like image 152
Moritz Avatar answered Oct 23 '22 04:10

Moritz


According to the documentation:

If the present length of the file as returned by the length method is smaller than the newLength argument then the file will be extended. In this case, the contents of the extended portion of the file are not defined.

Try this instead:

byte[] bytes = new byte[1024 * 1024 * 10];
MockMultipartFile firstFile = new MockMultipartFile("data", "file1.txt", "text/plain", bytes);
like image 32
jny Avatar answered Oct 23 '22 05:10

jny