问题
实际上,这是一种"follow-up" question。我有2个集成测试正在运行,用于文件上传,测试了相应的控制器。不幸的是,在使用了我另一个问题的答案的解决方案之后,应该“失败”的第二次集成测试(因为文件的扩展名是“错误的”,因此FileContainerValidator应该拒绝该文件)不会失败!验证程序甚至没有被调用。
该如何解决呢?
我的密码
FileUploadController
@Controller
public class FileUploadController {
private final FileStorageService fileStorageService;
FileContainerValidator fileContainerValidator;
@Autowired
public FileUploadController(FileStorageService FileStorageService) {
this.fileStorageService = FileStorageService;
}
@Autowired
public void setDefaultFileContainerValidator(FileContainerValidator validator) {
this.fileContainerValidator = validator;
}
@GetMapping("/upload")
public String showTestFileUploadForm(@ModelAttribute Mapping mapping, FileContainer fileContainer, Model model) {
String path = "ERROR";
try {
path = new ClassPathResource("data.csv").getFile().getPath();
} catch (IOException e) {
e.printStackTrace();
}
model.addAttribute("shortenedFile", new TableConstructor(path, mapping.getContentDelimiter()));
return "upload";
}
@PostMapping("/upload")
public String uploadFile(Model model, @Valid FileContainer fileContainer, BindingResult result) {
if (!result.hasErrors()) {
System.out.println("Fetching file");
fileStorageService.store(fileContainer);
//TODO: SUCCESS
model.addAttribute("success", true);
}
return "upload";
}
@InitBinder("fileContainer")
protected void initBinderFileContainer(WebDataBinder binder) {
binder.setValidator(fileContainerValidator);
}
}
FileUploadIntegrationTest@RunWith(SpringRunner.class)
@WebMvcTest(FileUploadController.class)
public class FileUploadIntegrationTest {
@Autowired
private MockMvc mockMvc;
@MockBean
private FileStorageService fileStorageService;
@MockBean
private FileContainerValidator fileContainerValidator;
private MockMultipartFile correctFile =
new MockMultipartFile("file", "filename.xml", "text/plain", "some xml".getBytes());
private MockMultipartFile fileWithWrongExtension =
new MockMultipartFile("file", "filename.txt", "text/plain", "this is a wrong file!".getBytes());
private String testDestination = "/tmp";
//THIS ONE WORKS
@Test
public void uploadMultipartTestFile() throws Exception {
when(fileContainerValidator.supports(any(Class.class))).thenReturn(true);
mockMvc.perform(MockMvcRequestBuilders.fileUpload("/upload")
.file(correctFile)
.param("destination", "/tmp"))
.andExpect(model().attribute("success", true));
}
//THIS ONE DOES NOT WORK
@Test
public void errorOnUploadFileWithWrongExtension() throws Exception {
when(fileContainerValidator.supports(any(Class.class))).thenReturn(true);
mockMvc.perform(MockMvcRequestBuilders.fileUpload("/upload")
.file(fileWithWrongExtension)
.param("destination", "/tmp"))
.andExpect(model().attributeHasFieldErrors("fileContainer.file"));
}
}
FileContainerValidator@Component
public class FileContainerValidator implements Validator {
public boolean supports(Class<?> clazz) {
return FileContainer.class.equals(clazz);
}
@Override
public void validate(Object obj, Errors errors) {
FileContainer fileContainer = (FileContainer) obj;
MultipartFile file = fileContainer.getFile();
String destination = fileContainer.getDestination();
if (file != null) {
if (file.getSize() == 0) {
errors.rejectValue("file", "missing.file", "The file must not be null or empty!");
}
if(file.getOriginalFilename().contains(".")) {
String extension = file.getOriginalFilename().split("\\.")[1];
if (!extension.equalsIgnoreCase("xml") && !extension.equalsIgnoreCase("csv")) {
errors.rejectValue("file", "extension.file", "The file had the wrong extension!");
}
} else {
errors.rejectValue("file", "extension.file", "The file had the wrong extension!");
}
} else {
errors.rejectValue("file", "missing.file", "The file must not be null or empty!");
}
if(destination != null && !destination.isEmpty()){
if(!destination.matches("([a-zA-Z]:)?(\\/[a-zA-Z0-9_.-]+)+\\/?"))
errors.rejectValue("destination", "wrong.destination", "The destination is given wrong");
} else {
errors.rejectValue("destination", "missing.destination", "The destination is missing");
}
}
}
表格(“upload.html”)<!DOCTYPE html SYSTEM "http://www.thymeleaf.org/dtd/xhtml1-strict-thymeleaf-spring4-4.dtd">
<html xmlns:th="http://www.thymeleaf.org" lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head th:include="head :: head (pagename='Upload File')"></head>
<body>
<div th:replace="fragments/nav :: nav">© Static</div>
<div class="panel panel-default" id="welcome-panel">
<div class="panel-heading">
<h2>Upload File</h2>
</div>
<div class="panel-body">
<div class="alert alert-success" th:if="${success}">File successfully uploaded!</div>
<form method="POST" action="#" th:action="@{/upload}" th:object="${fileContainer}"
enctype="multipart/form-data">
<h4>Upload files here:</h4>
<label for="file" class="upload-drop-zone">
Just drag and drop files <br> or click to upload.
<input type="file" th:field="*{file}" id="file" style="display:none;"/>
</label>
<br><br>
<label for="destination">Destination:</label>
<input type="text" value="/tmp" id="destination" th:field="*{destination}"/>
<br>
<button class="btn btn-success convert-button btn-block" type="submit" name="upload" id="upload">Create
</button>
<div class="alert alert-danger" th:if="${#fields.hasErrors('file')}" th:errors="*{file}"></div>
<div class="alert alert-danger" th:if="${#fields.hasErrors('destination')}"
th:errors="*{destination}"></div>
</form>
</div>
</div>
</div>
</body>
</html>
最佳答案
您不再使用“真实”的FileContainerValidator
。
@MockBean
private FileContainerValidator fileContainerValidator;
这就要求Spring为您的
FileContainerValidator
创建一个伪造的版本。因此
FileContainerValidator
内部的任何真实代码都将不再被调用。如果您使用:
@SpyBean
private FileContainerValidator fileContainerValidator;
那确实使用了真正的实现,但是允许您模拟出奇数方法。因此,您对
fileContainerValidator.supports
方法的嘲笑应该仍然有效。关于java - Spring-验证程序不会在集成测试中触发,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/41016228/