[FIXED] Spring Boot 2.5.0 – REST controller, MockMvc not UTF-8

Issue

In my REST controller I use
@PostMapping, @GetMapping, etc. without any other specification.

The default must be therefore JSON, for example for @GetMapping. Also there is no specification of the character encoding, it must be UTF-8 I assume, I couldn’t finde the default character encoding in the documentation.

However in my tests I use MockMvc.
When I do a POST request, it looks like this:

public static MvcResult performPost(MockMvc mockMvc, String endpoint, String payload, ResultMatcher status) throws Exception {
    MvcResult mvcResult = mockMvc.perform(
        post(endpoint)
            .content(payload)
            .contentType(MediaType.APPLICATION_JSON_VALUE))
        .andDo(print())
        .andExpect(status)
        .andReturn();

    return mvcResult;
}

Question:
The .andDo(print()) part seems not to use UTF-8. How to fix this? Some characters like the german 'ü' are not printed correctly in the console of my NetBeans IDE. It looks like (see Body):

MockHttpServletResponse:
           Status = 200
    Error message = null
          Headers = [Content-Type:"application/json", X-Content-Type-Options:"nosniff", X-XSS-Protection:"1; mode=block", Cache-Control:"no-cache, no-store, max-age=0, must-revalidate", Pragma:"no-cache", Expires:"0", X-Frame-Options:"DENY"]
     Content type = application/json
             Body = {"Tür"}
    Forwarded URL = null
   Redirected URL = null
          Cookies = []

Question:
When my method returns MvcResult, I can do:

MockHttpServletResponse response = mvcResult.getResponse(); 
ObjectMapper objectMapper = new ObjectMapper();
    
String contentAsString = response.getContentAsString(StandardCharsets.UTF_8);

I figured out, that I have to use StandardCharset.UTF_8 to obtain the correct characters, like 'ü'.

But why is in MockHttpServletResponse response the characterEncoding ISO-8859-1? Where does ISO-8859-1 come from, where is this set? Can it be changed to UTF-8?

When I instead try:

String contentAsString = response.getContentAsString(StandardCharsets.ISO_8859_1);

I don’t get the german 'ü', the String value is "Tür". Although in ISO_8859_1 according to https://en.wikipedia.org/wiki/ISO/IEC_8859-1 the character 'ü' is in the Code page layout table.

Solution

This answer to a related question shows how to set the default encoding for all tests (indeed the documentation does not specify what is the default).

If you don’t want to rely on (yet another) configuration item set up outside the tests, I believe setting the encoding in the request will automatically make MockMvc do the right thing. We do that in our tests where JSON payloads carry accented characters.

 MvcResult mvcResult = mockMvc.perform(
    post(endpoint)
        .content(payload)
        .contentType(MediaType.APPLICATION_JSON_VALUE)
        .characterEncoding("utf-8"))
    .andDo(print())
    .andExpect(status)
    .andReturn();

Answered By – Paulo Merson

Answer Checked By – Clifford M. (Easybugfix Volunteer)

Leave a Reply

(*) Required, Your email will not be published