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

Print request body in PrintingResultHandler in Spring MVC Test [SPR-14717] #19282

Closed
spring-projects-issues opened this issue Sep 15, 2016 · 7 comments

Comments

@spring-projects-issues
Copy link
Collaborator

@spring-projects-issues spring-projects-issues commented Sep 15, 2016

Manuel Jordan opened SPR-14717 and commented

Form Submission

The following applies to form submission via POST and PUT requests.

I have the following handler method that processes a form submission via POST.

@PostMapping(value="/save",
                          consumes=MediaType.APPLICATION_FORM_URLENCODED_VALUE,
                          produces=MediaType.TEXT_HTML_VALUE)
public String saveOne(@Validated @ModelAttribute Persona persona,
                                     BindingResult result,
                                     RedirectAttributes redirectAttributes){

And this is the test:

resultActions = mockMvc.perform(post(url).contentType(MediaType.APPLICATION_FORM_URLENCODED)
               .param("id", persona.getId())
               .param("nombre", persona.getNombre())
               .param("apellido", persona.getApellido())
               .param("fecha", ... )
               .andDo(print());

Using andDo(print()), I can see the following:

MockHttpServletRequest:
      HTTP Method = POST
      Request URI = /personas/save.html
       Parameters = {id=[700], nombre=[Filipito], apellido=[Jordan], fecha=[06/16/1988]}
          Headers = {Content-Type=[application/x-www-form-urlencoded]}

From that I can confirm and see what I am sending to the server. Until here I am fine.

XML or JSON payload in request body

Regarding REST requests, I have the following handler method.

@PostMapping(consumes={MediaType.APPLICATION_XML_VALUE,  
                              MediaType.APPLICATION_JSON_UTF8_VALUE})
public ResponseEntity<Void> saveOne(@Validated @RequestBody Persona persona){

And these are the tests:

resultActions = mockMvc.perform(post(uri).contentType(MediaType.APPLICATION_XML)
                        .content(....persona....))).andDo(print());
resultActions = mockMvc.perform(post(uri).contentType(MediaType.APPLICATION_JSON_UTF8)
                        .content(....persona....))).andDo(print());

For both XML and JSON I am again using .andDo(print()) which results in the following.

MockHttpServletRequest:
      HTTP Method = POST
      Request URI = /personas
       Parameters = {}
          Headers = {Content-Type=[application/json;charset=UTF-8]}
...etc

and

MockHttpServletRequest:
      HTTP Method = POST
      Request URI = /personas
       Parameters = {}
          Headers = {Content-Type=[application/xml]}
...etc

Where ...etc provides additional information but does not print the XML or JSON body of the request.

Workaround

If I use RestTemplate, I can print the RequestEntity object (e.g., via logging).

Proposal

I would like to see the REST request body when using MockMvc.


Referenced from: commits 487bc75, 04b8ae9

@spring-projects-issues
Copy link
Collaborator Author

@spring-projects-issues spring-projects-issues commented Sep 15, 2016

Sam Brannen commented

FYI: the code in question here is in PrintingResultHandler (which backs the doPrint() method).

Specifically, printRequest() prints input parameters but does not print the request body.

However, printResponse() does in fact print the response body by invoking MockHttpServletResponse.getContentAsString().

Thus a solution for this issue would be to introduce similar support in printRequest() that prints the request body retrieved via MockHttpServletRequest.getReader().

Alternatively, we could introduce a dedicated getContentAsString() method in MockHttpServletRequest for this purpose.

@spring-projects-issues
Copy link
Collaborator Author

@spring-projects-issues spring-projects-issues commented Sep 15, 2016

Manuel Jordan commented

Hello Sam

FYI: the code in question here is in PrintingResultHandler (which backs the doPrint() method).

Understood

Specifically, printRequest() prints input parameters but does not print the request body.

Ok, it is the current behaviour.

However, printResponse() does in fact print the response body by invoking MockHttpServletResponse.getContentAsString().

Yes, I have none problem about the Get method, it applies for XML and JSON formats when some data has been retrieved.

Thus a solution for this issue would be to introduce similar support in printRequest() that prints the request body retrieved via MockHttpServletRequest.getReader().
Alternatively, we could introduce a dedicated getContentAsString() method in MockHttpServletRequest for this purpose

Sounds great!...

Thanks Sam.

@spring-projects-issues
Copy link
Collaborator Author

@spring-projects-issues spring-projects-issues commented Sep 15, 2016

Rossen Stoyanchev commented

However, printResponse() does in fact print the response body by invoking MockHttpServletResponse.getContentAsString().

The response body is the end result of request handling after invoking MockMvc. Most certainly it's something you'll want to verify and also might want to print/see. The request body on the other hand is exactly what was provided a few lines earlier in the test as input. So in that sense a lot less interesting to see. You already know what it is.

The same generally applies to the MockHttpServletRequest and Response. Typically you set up the request as part of the test but the response is updated by the code under test, which probably explains why we only have a getContentAsString() in the response and not in the request.

Of course no harm in having a getContent() methods in the mock request. My main concern with automatically printing is that it makes it unusable if the body is not textual content, so I would add some checks before printing. Something similar perhaps to what we do in StompHeaderAccessor#appendPayload? A similar improvement could be made for printing the response body too.

@spring-projects-issues
Copy link
Collaborator Author

@spring-projects-issues spring-projects-issues commented Sep 15, 2016

Sam Brannen commented

That's very valid and insightful input Rossen Stoyanchev, and the StompHeaderAccessor#appendPayload tip could in fact make sense both for the request and the response.

Cheers!

@spring-projects-issues
Copy link
Collaborator Author

@spring-projects-issues spring-projects-issues commented Oct 3, 2016

Sam Brannen commented

Partially resolved in GitHub commit 04b8ae92:

Introduce getContentAsByteArray()/getContentAsString() in MockHtttpSvltReq

In order to improve debugging and logging within test suites, this
commit introduces getContentAsByteArray() and getContentAsString()
methods in MockHttpServletRequest, analogous to the existing methods in
MockHttpServletResponse.

@spring-projects-issues
Copy link
Collaborator Author

@spring-projects-issues spring-projects-issues commented Oct 3, 2016

Sam Brannen commented

Completed in GitHub commit 487bc75:

Print request body in PrintingResultHandler in Spring MVC Test

Prior to this commit, the PrintingResultHandler used by the various
print() and log() methods in Spring MVC Test printed the response body
but not the request body.

Since request bodies are sometimes generated programmatically, however,
it can be beneficial to have the dynamically generated request body
logged as well.

This commit therefore prints the request body in PrintingResultHandler
by delegating to the recently introduced getContentAsString() method in
MockHttpServletRequest.

@spring-projects-issues
Copy link
Collaborator Author

@spring-projects-issues spring-projects-issues commented Oct 3, 2016

Sam Brannen commented

Rossen Stoyanchev, your tip regarding readable content will be addressed in #19342.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
2 participants