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

Cannot test @RequestPart multipart controllers with Servlet MockPart #25829

Closed
dimone-kun opened this issue Sep 28, 2020 · 7 comments
Closed
Assignees
Labels
in: web Issues in web modules (web, webmvc, webflux, websocket) status: backported An issue that has been backported to maintenance branches type: enhancement A general enhancement
Milestone

Comments

@dimone-kun
Copy link

Tested with spring boot 2.3.4.
Example project

We have controller that receives some arguments that are parts of multipart request.

@RestController
class HelloWorldController {
    @RequestMapping(path = "helloworld", method = RequestMethod.POST)
    @ResponseStatus(code = HttpStatus.OK)
    public String helloWorld(@RequestPart(name = "part0") String str0,
                             @RequestPart(name = "part1") String str1) {
        return str0+str1;
    }
}

For running application request works as intended:

POST http://localhost:8080/helloworld
Content-Type: multipart/form-data; boundary=6512c604-1edc-4c15-8916-dc2e91413c82

--6512c604-1edc-4c15-8916-dc2e91413c82
Content-Disposition: form-data;name="part0"
Content-Type: text/plain

Hello
--6512c604-1edc-4c15-8916-dc2e91413c82
Content-Disposition: form-data;name="part1"
Content-Type: text/plain

World
--6512c604-1edc-4c15-8916-dc2e91413c82--

## response HelloWorld

Now we want to test it:

@Test
void helloWorldTest() throws Exception {
        MockPart part0 = new MockPart("part0", "Hello".getBytes());
        part0.getHeaders().setContentType(MediaType.TEXT_PLAIN);
        MockPart part1 = new MockPart("part1", "World".getBytes());
        part1.getHeaders().setContentType(MediaType.TEXT_PLAIN);

        web.perform(multipart("/helloworld")
                .part(part0, part1))
                .andExpect(status().isOk())
                .andExpect(content().string("HelloWorld"));
}

But test is failing with NPE exception:

Request processing failed; nested exception is java.lang.NullPointerException
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is java.lang.NullPointerException
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:652)
Caused by: java.lang.NullPointerException
	at org.springframework.web.multipart.support.RequestPartServletServerHttpRequest.getBody(RequestPartServletServerHttpRequest.java:99)

The reason behind that is org.springframework.web.multipart.support.RequestPartServletServerHttpRequest:84; it's expecting StandardMultipartHttpServletRequest in multipartRequest field but got MockMultipartHttpServletRequest:

public InputStream getBody() throws IOException {
    if (this.multipartRequest instanceof StandardMultipartHttpServletRequest) {
        try {
            return this.multipartRequest.getPart(this.partName).getInputStream();
        }
        catch (Exception ex) {
            throw new MultipartException("Could not parse multipart servlet request", ex);
        }
    }
    <...>
}
@philwebb
Copy link
Member

RequestPartServletServerHttpRequest and MockMultipartHttpServletRequest are part of Spring Framework. I'll transfer your issue for that team to consider. Perhaps that instanceof check should be for a org.springframework.web.multipart.MultipartHttpServletRequest?

@philwebb philwebb transferred this issue from spring-projects/spring-boot Sep 28, 2020
@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged or decided on label Sep 28, 2020
@JWThewes
Copy link

Wouldn't this be ideal for a first contribution? I would be absolutely willing to fix this.

@JWThewes
Copy link

I created a PR for this. This is one idea to solve the problem. Existing tests work and the mentioned problem is fixed (validated via test). I would love to get feedback for further PRs.

@sbrannen sbrannen added the in: web Issues in web modules (web, webmvc, webflux, websocket) label Sep 29, 2020
@jhoeller jhoeller self-assigned this Sep 29, 2020
@jhoeller jhoeller added type: enhancement A general enhancement and removed status: waiting-for-triage An issue we've not yet triaged or decided on labels Sep 29, 2020
@jhoeller jhoeller added this to the 5.2.10 milestone Sep 29, 2020
@jhoeller jhoeller changed the title NPE in tests of Multipart controllers with @RequestPart Cannot test @RequestPart multipart controllers with Servlet MockPart Sep 29, 2020
@rstoyanchev
Copy link
Contributor

I wonder if this isn't a duplicate of #25602?

@rstoyanchev
Copy link
Contributor

I confirm the example project works against master but fails with 5.2.x.

@dimone-kun
Copy link
Author

I wonder if this isn't a duplicate of #25602?

It seems that it is. Sorry didn't find that issue.

@rstoyanchev
Copy link
Contributor

No worries, it's not very obvious and at the time I fixed it for the upcoming 5.3 only but this does show it would be beneficial to have a fix in 5.2.x as well.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: web Issues in web modules (web, webmvc, webflux, websocket) status: backported An issue that has been backported to maintenance branches type: enhancement A general enhancement
Projects
None yet
Development

Successfully merging a pull request may close this issue.

7 participants