Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce MockPart in spring-test [SPR-14252] #18825

Closed
spring-projects-issues opened this issue May 5, 2016 · 4 comments
Closed

Introduce MockPart in spring-test [SPR-14252] #18825

spring-projects-issues opened this issue May 5, 2016 · 4 comments
Assignees
Labels
in: test Issues in the test module type: enhancement A general enhancement
Milestone

Comments

@spring-projects-issues
Copy link
Collaborator

spring-projects-issues commented May 5, 2016

Sam Brannen opened SPR-14252 and commented

Status Quo

Spring already has a mock for javax.servlet.http.Part in the test source folder in spring-web; however, there is currently no counterpart in the spring-test module for public consumption.

Further Analysis

As pointed out by a user on Stack Overflow, it is currently not possible to mock Part on your own due to the following:

In RequestPartServletServerHttpRequest I run into this:

this.headers = this.multipartRequest.getMultipartHeaders(this.partName);
if (this.headers == null) {
    throw new MissingServletRequestPartException(partName);
} 

It is therefore likely that we will need to modify MockMultipartHttpServletRequest as well. In particular, the contract for Spring's MultipartHttpServletRequest.getMultipartHeaders() states the following.

Return the headers associated with the specified part of the multipart request.

If the underlying implementation supports access to headers, then all headers are returned. Otherwise, the returned headers will include a 'Content-Type' header at the very least.

However, MockMultipartHttpServletRequest.getMultipartHeaders() in fact returns null if the content type for the part cannot be retrieved. This is because Spring's MultipartRequest.getMultipartContentType() specifies that it will return the associated content type, or null if not defined. Thus, there is definitely a conflict between these two contracts. Most importantly, MockMultipartHttpServletRequest.getMultipartContentType() only supports look-ups for MultipartFile and disregards any Part that might be present.

Deliverables

  • Introduce a mock for javax.servlet.http.Part in spring-test based on the existing org.springframework.mock.web.test.MockPart in spring-web, potentially implementing write() and delete() as well.

Reference URL: http://stackoverflow.com/questions/37000457/setting-request-parts-in-spring-test-mvc

Issue Links:

Referenced from: commits c8f98ec

1 votes, 4 watchers

@spring-projects-issues
Copy link
Collaborator Author

spring-projects-issues commented Jan 25, 2017

Sam Brannen commented

Thanks, Rossen! (y)

@spring-projects-issues
Copy link
Collaborator Author

spring-projects-issues commented Aug 17, 2017

Sarah Lilie commented

Could someone offer me an example of how to use the MockPart in spring test? I'm trying to mock a request with a MultipartFile and a JSON object

@RequestMapping(method = RequestMethod.POST)
public ResponseEntity<AnalyticMetadata> createObject(@RequestPart("object") CustomObject object, @RequestPart("file") MultipartFile file)

I tried the following request but it complains with exception "Required request part 'object' is not present"

MockMultipartFile multiPartFile = new MockMultipartFile("file", "filename.zip", null, is);
MockPart part = new MockPart("object", mapper.writeValueAsBytes(customObject));

mockMvc.perform(MockMvcRequestBuilders.multipart("/").file(multiPartFile).part(part)).andExpect(status().isCreated())
                .andExpect(jsonPath("$.id").isNotEmpty());

@spring-projects-issues
Copy link
Collaborator Author

spring-projects-issues commented Aug 17, 2017

Sam Brannen commented

Hi Sarah Lilie,

The following is an example taken from the org.springframework.test.web.servlet.samples.standalone.MultipartControllerTests test class in Spring's own test suite.

@Test
public void multipartRequestWithServletParts() throws Exception {
	byte[] fileContent = "bar".getBytes(StandardCharsets.UTF_8);
	MockPart filePart = new MockPart("file", "orig", new ByteArrayInputStream(fileContent));

	byte[] json = "{\"name\":\"yeeeah\"}".getBytes(StandardCharsets.UTF_8);
	MockPart jsonPart = new MockPart("json", "json", new ByteArrayInputStream(json));
	jsonPart.getHeaders().setContentType(MediaType.APPLICATION_JSON);

	standaloneSetup(new MultipartController()).build()
			.perform(multipart("/test-multipartfile").part(filePart).part(jsonPart))
			.andExpect(status().isFound())
			.andExpect(model().attribute("fileContent", fileContent))
			.andExpect(model().attribute("jsonContent", Collections.singletonMap("name", "yeeeah")));
}

Hope this helps!

@spring-projects-issues
Copy link
Collaborator Author

spring-projects-issues commented Aug 17, 2017

Sarah Lilie commented

Hi @Sam Brannen, thanks for the tip! I was able to get it working! :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: test Issues in the test module type: enhancement A general enhancement
Projects
None yet
Development

No branches or pull requests

2 participants