使用 MockMultipartFile 测试最大上传文件大小
Posted
技术标签:
【中文标题】使用 MockMultipartFile 测试最大上传文件大小【英文标题】:Test maximum upload file size with MockMultipartFile 【发布时间】:2016-02-13 12:45:15 【问题描述】:我使用 Spring Boot 创建了一个文件上传服务,并使用 Spring Mock Mvc 和 MockMultipartFile 对其进行了测试。我想测试超过最大文件大小时是否引发错误。以下测试失败,因为它收到 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());
有没有可能测试上传文件的大小?
【问题讨论】:
您在哪里指定了最大上传大小? 【参考方案1】:根据documentation:
如果 length 方法返回的文件的当前长度是 小于 newLength 参数,则文件将被扩展。在 在这种情况下,文件扩展部分的内容不是 已定义。
试试这个:
byte[] bytes = new byte[1024 * 1024 * 10];
MockMultipartFile firstFile = new MockMultipartFile("data", "file1.txt", "text/plain", bytes);
【讨论】:
这对我不起作用。是否有可能使用 MockMVC 禁用文件大小检查? @wuethrich44:看起来确实如此。我偶然发现了同样的问题,也找不到简单的解决方案。在不查看spring-web
的代码(或任何应该处理的代码)的情况下,我不禁注意到某些 Tomcat 代码(ie)抛出了实际的异常(超出限制) >java.lang.IllegalStateException: org.apache.tomcat.util.http.fileupload.FileUploadBase$FileSizeLimitExceededException: The field file exceeds its maximum permitted size of 1048576 bytes.
)。所以也许 Spring 只是将这个检查委托给底层应用程序服务器。
@wuethrich44:因为MockMvc
集成测试并没有真正包含实际的应用服务器...
@PriiduNeemre 好的,当 Tomcat 处理此错误时,似乎无法在 MockMvc
中进行测试。奇怪的是@David Jones 在这个解决方案上取得了成功......
David 可能正在做手动大小检查以及/而不是使用 Spring 属性。【参考方案2】:
这里有同样的问题。
不知道是否有更好的解决方案,但我创建了一个注释来验证上传的图像列表,并在那里与其他人一起检查。
验证图像的类 public class ImageValidator implements ConstraintValidator<ValidImage, List<MultipartFile>>
@Override
public boolean isValid(
List<MultipartFile> listMultipartFile, ConstraintValidatorContext context)
for (var multipartFile : listMultipartFile)
var msgValidation = imageValidations(multipartFile);
if (!msgValidation.isEmpty())
context.disableDefaultConstraintViolation();
context.buildConstraintViolationWithTemplate(msgValidation).addConstraintViolation();
return false;
return true;
private String imageValidations(MultipartFile multipartFile)
var contentType = multipartFile.getContentType();
if (!isSupportedContentType(contentType))
return String.format(
"Only JPG and PNG images are allowed, %s provided.", multipartFile.getContentType());
else if (multipartFile.isEmpty())
return "It must not be an empty image.";
else if (multipartFile.getSize() > (1024 * 1024))
return "File size should be at most 1MB";
return "";
private boolean isSupportedContentType(String contentType)
var supportedContents = List.of("image/jpg", "image/jpeg", "image/png");
return supportedContents.contains(contentType);
接口
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = ImageValidator.class)
public @interface ValidImage
String message() default "Invalid image file";
Class<?>[] groups() default ;
Class<? extends Payload>[] payload() default ;
【讨论】:
【参考方案3】:你不能用 Spring 的 MockMultipartFile / MockMvc 测试这个。原因是错误的来源不是 Spring 本身,而是底层 Web 服务器(通常是 Tomcat),正如您在 MaxUploadSizeExceededException 的堆栈跟踪中看到的那样:
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
当使用默认的 MockMvc 和 @SpringBootTest
及其默认设置时,没有启动真正的 Web 服务器,因此不会发生错误。
但是,您可以通过提供@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
来告诉 Spring 为您的测试启动一个真正的 Web 服务器,这将(惊喜)在一个随机端口上启动一个 Web 服务器。您可以在测试类中使用@LocalServerPort
访问该端口。
然后您可以编写一个测试,对您的测试服务器执行真实分段上传,而不是伪造的。 REST Assured 是一个库,除其他外,它可以做到这一点:
@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");
...
当您的上传过大时,此测试将显示服务器错误。
【讨论】:
以上是关于使用 MockMultipartFile 测试最大上传文件大小的主要内容,如果未能解决你的问题,请参考以下文章
在训练数据上使用 MinMaxScaler 以生成用于测试数据的标准、最小值和最大值
最大限度。 Visual Studio 负载测试中的负载测试运行持续时间
使用 Oracle 的 Spring Boot 应用程序 - ORA-01000:超出最大打开游标 - 负载测试期间发生错误