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

Support default character encoding for response in MockMvc #27230

Closed
1 task done
sbrannen opened this issue Jul 30, 2021 · 2 comments
Closed
1 task done

Support default character encoding for response in MockMvc #27230

sbrannen opened this issue Jul 30, 2021 · 2 comments
Assignees
Labels
in: test Issues in the test module in: web Issues in web modules (web, webmvc, webflux, websocket) type: enhancement A general enhancement
Milestone

Comments

@sbrannen
Copy link
Member

sbrannen commented Jul 30, 2021

Overview

#27214 introduced support for setting the default character encoding in MockHttpServletResponse, and the focus of this issue is to make that configurable when building an instance of MockMvc.

Deliverables

  • Introduce defaultResponseCharacterEncoding(Charset) in ConfigurableMockMvcBuilder and use it to configure the default character encoding in the underlying MockHttpServletResponse.
@sbrannen sbrannen added in: test Issues in the test module in: web Issues in web modules (web, webmvc, webflux, websocket) type: enhancement A general enhancement labels Jul 30, 2021
@sbrannen sbrannen added this to the 5.3.10 milestone Jul 30, 2021
@sbrannen sbrannen self-assigned this Jul 30, 2021
sbrannen added a commit to sbrannen/spring-framework that referenced this issue Sep 6, 2021
…ng()

This commit updates the defaultResponseCharacterEncoding() `default`
method in ConfigurableMockMvcBuilder so that it throws an
UnsupportedOperationException instead of silently ignoring the user's
request to set the default response character encoding.

Note, however, that AbstractMockMvcBuilder already overrides the
default method with a concrete implementation which is used by default
in MockMvc.

See spring-projectsgh-27230
sbrannen added a commit to sbrannen/spring-framework that referenced this issue Sep 6, 2021
lxbzmy pushed a commit to lxbzmy/spring-framework that referenced this issue Mar 26, 2022
Commit e4b9b1f introduced support for setting the default character
encoding in MockHttpServletResponse.

This commit introduces support for configuring the default character
encoding in the underlying MockHttpServletResponse used in MockMvc.

Closes spring-projectsgh-27230
lxbzmy pushed a commit to lxbzmy/spring-framework that referenced this issue Mar 26, 2022
…ng()

This commit updates the defaultResponseCharacterEncoding() `default`
method in ConfigurableMockMvcBuilder so that it throws an
UnsupportedOperationException instead of silently ignoring the user's
request to set the default response character encoding.

Note, however, that AbstractMockMvcBuilder already overrides the
default method with a concrete implementation which is used by default
in MockMvc.

See spring-projectsgh-27230
lxbzmy pushed a commit to lxbzmy/spring-framework that referenced this issue Mar 26, 2022
@lonre
Copy link
Contributor

lonre commented Nov 17, 2023

Hi @sbrannen

Could you please help to check this test case, it still fails

import static java.nio.charset.StandardCharsets.UTF_8;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static org.springframework.test.web.servlet.setup.MockMvcBuilders.standaloneSetup;

import org.junit.jupiter.api.Test;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;


class ResponseBodyTests {

	@Test
	void text() throws Exception {

		standaloneSetup(new PersonController()).defaultResponseCharacterEncoding(UTF_8).build()
				.perform(post("/person").characterEncoding(UTF_8).content("Jürgen"))
				.andDo(print())
				.andExpect(status().isOk())
				.andExpect(content().string("Jürgen"));
	}


	@RestController
	private static class PersonController {
		@PostMapping("/person")
		String post(@RequestBody String content) {
			return content;
		}
	}

}

@sbrannen
Copy link
Member Author

Hi @lonre,

Thanks for providing the failing test case.

I took a look at it, and it appears that the defaultResponseCharacterEncoding has no effect for String payloads with the default configuration for Spring MVC.

Behind the scenes, a default instance of StringHttpMessageConverter is used for reading and writing the content, and in order to have it treat the content as UTF-8 encoded text for both the request and the response, you have to explicitly specify that as follows.

class RestUtf8StringPayloadTests {

	@Test
	void test() throws Exception {
		MockMvc mockMvc = standaloneSetup(new PersonController())
				// .defaultResponseCharacterEncoding(StandardCharsets.UTF_8)
				.build();

		mockMvc.perform(post("/person")
							.contentType("text/plain;charset=UTF-8")
							.accept("text/plain;charset=UTF-8")
							.content("Jürgen")
						)
				.andDo(print())
				.andExpect(status().isOk())
				.andExpect(content().encoding(StandardCharsets.UTF_8))
				.andExpect(content().string("Jürgen"));
	}


	@RestController
	private static class PersonController {
		@PostMapping("/person"))
		String post(@RequestBody String content) {
			return content;
		}
	}

}

As an alternative to specifying .accept("text/plain;charset=UTF-8") for the POST with MockMvc, you can specify that the controller method produces text/plain;charset=UTF-8 as in the following modified example.

class RestUtf8StringPayloadTests {

	@Test
	void test() throws Exception {
		standaloneSetup(new PersonController()).build()
				.perform(post("/person")
							.contentType("text/plain;charset=UTF-8")
							.content("Jürgen")
						)
				.andDo(print())
				.andExpect(status().isOk())
				.andExpect(content().encoding(StandardCharsets.UTF_8))
				.andExpect(content().string("Jürgen"));
	}


	@RestController
	private static class PersonController {
		@PostMapping(path = "/person", produces = "text/plain;charset=UTF-8")
		String post(@RequestBody String content) {
			return content;
		}
	}

}

⚠️ In both examples above, it is required that you specify not only the character encoding (UTF-8) but also the Content-Type (text/plain).

I believe this may be the expected behavior for StringHttpMessageConverter; however, I'll clarify that with @rstoyanchev.

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 in: web Issues in web modules (web, webmvc, webflux, websocket) type: enhancement A general enhancement
Projects
None yet
Development

No branches or pull requests

2 participants