Support RestAssuredMockMvc
If you try to use MockMvc validator in RestAssuredMockMvc environment:
given()
.contentType(MediaType.APPLICATION_JSON_VALUE)
.when()
.post("xxx")
.then()
.expect(openApi().isValid("api.json));
you get:
java.lang.IllegalStateException: Cannot call getReader() after getInputStream() has already been called for the current request
at org.springframework.mock.web.MockHttpServletRequest.getReader(MockHttpServletRequest.java:716)
at com.atlassian.oai.validator.mockmvc.MockMvcRequest.getReader(MockMvcRequest.java:119)
at com.atlassian.oai.validator.mockmvc.MockMvcRequest.getBody(MockMvcRequest.java:100)
at com.atlassian.oai.validator.mockmvc.MockMvcRequest.of(MockMvcRequest.java:91)
at com.atlassian.oai.validator.mockmvc.OpenApiMatchers.lambda$isValid$0(OpenApiMatchers.java:56)
This happens because RestAssuredMockMvc calls getInputStream() on MockHttpServletRequest, and MockMvc validator calls getReader() on the same MockHttpServletRequest, which can't be done according to servlet specs:
Either this method
* or {@link #getInputStream} may be called to read the body, not both.
Comments (6)
-
-
Is it possible to switch to
getContentAsByteArray()
as they suggest doing?
-
I can reproduce the error in a unit test.
However it is not that simple to correct that behaviour.
The method
MockHttpServletRequest#getContentAsByteArray()
was introduced in Spring 5. TheOpenApiMatchers
is supporting Spring 4. Changing that would break the backwards compability. All Spring Boot users prior v2.1.0 (released ~3 months ago) would have failing tests.There are several options.
- create a second
swagger-request-validator-mockmvc-v5
for Spring 5 or later - use reflection to prevent the error and receive the requests body even for Spring 5
- knock on Springs doors and complaining about that new behaviour as @illia-olx already did here: https://github.com/spring-projects/spring-framework/issues/21048#issuecomment-456006830
Any other ideas?
- create a second
-
I don't want to break backwards compatibility either and those are also the options I came up with.
My favoured approach:
- Rename the current pre Spring 5.1 supporting module to
swagger-request-validator-mockmvc
toswagger-request-validator-mockmvc-legacy
(following the naming convention from the spring-boot-legacy module that adds Servlet 2.5 support to to Spring Boot 2 and this discussion at Togglz) - Create a new
swagger-request-validator-mockmvc
module that supports Spring 5.1 onwards
pull request #121 implements these changes
- Rename the current pre Spring 5.1 supporting module to
-
Issue should be resolved in
v2.2.0
As described in the PR - if you are using Spring Boot < 2.1 (Spring < 5.1) you will need to change your dependency to
swagger-request-validator-mockmvc-legacy
-
- changed status to resolved
- Log in to comment
The MockMvc validator works with RestAssured when you use a version of Spring prior to 5.1. SPR-16499 changed the behaviour of
MockHttpServletRequest
to only disallow calls to callsgetInputStream()
andgetReader()
Unfortunately simply replacing the call to
getReader()
withgetInputStream()
causes us to run into the related SPR-16505 issue which changed the behaviour of MockHttpServletRequest to only allow the InputStream to only be read once.