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?
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.
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);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With