-
Notifications
You must be signed in to change notification settings - Fork 38.8k
Description
When testing an application using HtmlUnit, its often useful to use HtmlFileInput.setData(...) instead of HtmlFileInput.setFiles(...) in order to not have to generate temporary files. However, when using MockMvcWebClientBuilder, this doesn't work. The problem is that HtmlUnitRequestBuilder ignores the data part.
#24926 added support for file uploads in HtmlUnitRequestBuilder, but missed this use case.
Test case:
filesubmit.html:
<!DOCTYPE html>
<html>
<head>
<title>File submission test</title>
</head>
<body>
<form method="POST" action="/filesubmit" enctype="multipart/form-data">
File: <input name="file" type="file"/>
<button type="submit">Submit</button>
</form>
</body>
</html>FileSubmitController.java:
@Controller
public class FileSubmitController {
@PostMapping("/filesubmit")
public @ResponseBody String handleFileSubmit(@RequestParam(name = "file", required = false) MultipartFile file) {
return file == null ? "unset" : file.getOriginalFilename();
}
}FileSubmitTest.java:
@WebMvcTest(FileSubmitController.class)
public class FileSubmitTest {
@Autowired
WebClient webClient;
@Test
void testFileSubmitUsingFile() throws FailingHttpStatusCodeException, MalformedURLException, IOException {
HtmlPage page = webClient.getPage("/filesubmit.html");
HtmlFileInput file = page.querySelector("input[type=file]");
file.setContentType("application/json");
file.setFiles(new File("src/test/resources/test.json"));
HtmlButton submit = page.querySelector("button");
Page resultPage = submit.click();
// Succeeds
assertEquals("test.json", resultPage.getWebResponse().getContentAsString());
}
@Test
void testFileSubmitUsingData() throws FailingHttpStatusCodeException, MalformedURLException, IOException {
HtmlPage page = webClient.getPage("/filesubmit.html");
HtmlFileInput file = page.querySelector("input[type=file]");
file.setValueAttribute("test.json");
file.setContentType("application/json");
file.setData("{}".getBytes());
HtmlButton submit = page.querySelector("button");
Page resultPage = submit.click();
// Fails with expected: <test.json> but was: <unset>
assertEquals("test.json", resultPage.getWebResponse().getContentAsString());
}
}When starting the application normally and changing WebClient from a mocked version to a normal version using http://localhost:8080/ both tests succeed.
I'm guessing in HtmlUnitRequestBuilder.params(...), the else part should be something like this:
else { // use data
part = new MockPart(pair.getName(), pair.getValue(), pair.getData());
if (pair.getMimeType() == null)
part.getHeaders().setContentType(MediaType.APPLICATION_OCTET_STREAM);
else
part.getHeaders().setContentType(MediaType.valueOf(pair.getMimeType()));
}I'm not sure if there is a specific edge case to use the old "mimic empty file upload" else case.
Tested using Spring Boot 2.5.2 using Spring WebMVC 5.3.8.