Skip to content

Commit adadffe

Browse files
committed
Improve charset handling in MockHttpServletResponse
This commit adds a getContentAsString(Charset fallbackCharset) method to MockHttpServletResponse in order to make it easier to get the content in a specific charset like UTF-8 when the response charset has not been explicitly set (by default ISO-8859-1 is used). JsonPathResultMatchers leverages this new feature to support UTF-8 content out of the box. Closes gh-23219
1 parent 60a7092 commit adadffe

File tree

4 files changed

+47
-6
lines changed

4 files changed

+47
-6
lines changed

spring-test/src/main/java/org/springframework/mock/web/MockHttpServletResponse.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import java.io.PrintWriter;
2424
import java.io.UnsupportedEncodingException;
2525
import java.io.Writer;
26+
import java.nio.charset.Charset;
2627
import java.text.DateFormat;
2728
import java.text.ParseException;
2829
import java.text.SimpleDateFormat;
@@ -204,11 +205,32 @@ public byte[] getContentAsByteArray() {
204205
return this.content.toByteArray();
205206
}
206207

208+
/**
209+
* Get the content of the response body as a {@code String}, using the configured
210+
* {@linkplain #getCharacterEncoding character encoding}.
211+
* @return the content as a {@code String}
212+
* @throws UnsupportedEncodingException if the character encoding is not supported
213+
* @see #getContentAsString(Charset)
214+
*/
207215
public String getContentAsString() throws UnsupportedEncodingException {
208216
return (this.characterEncoding != null ?
209217
this.content.toString(this.characterEncoding) : this.content.toString());
210218
}
211219

220+
/**
221+
* Get the content of the response body as a {@code String}, using the provided
222+
* {@code fallbackCharset} if no charset has been explicitly defined, else using
223+
* using the configured {@linkplain #getCharacterEncoding character encoding}.
224+
* @return the content as a {@code String}
225+
* @throws UnsupportedEncodingException if the character encoding is not supported
226+
* @see #getContentAsString()
227+
*/
228+
public String getContentAsString(Charset fallbackCharset) throws UnsupportedEncodingException {
229+
return isCharset() ?
230+
this.content.toString(this.characterEncoding) :
231+
this.content.toString(fallbackCharset.name());
232+
}
233+
212234
@Override
213235
public void setContentLength(int contentLength) {
214236
this.contentLength = contentLength;

spring-test/src/main/java/org/springframework/test/web/servlet/result/JsonPathResultMatchers.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package org.springframework.test.web.servlet.result;
1818

1919
import java.io.UnsupportedEncodingException;
20+
import java.nio.charset.StandardCharsets;
2021

2122
import com.jayway.jsonpath.JsonPath;
2223
import org.hamcrest.Matcher;
@@ -235,7 +236,7 @@ public ResultMatcher isMap() {
235236
}
236237

237238
private String getContent(MvcResult result) throws UnsupportedEncodingException {
238-
String content = result.getResponse().getContentAsString();
239+
String content = result.getResponse().getContentAsString(StandardCharsets.UTF_8);
239240
if (StringUtils.hasLength(this.prefix)) {
240241
try {
241242
String reason = String.format("Expected a JSON payload prefixed with \"%s\" but found: %s",

spring-test/src/test/java/org/springframework/mock/web/MockHttpServletResponseTests.java

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package org.springframework.mock.web;
1818

1919
import java.io.IOException;
20+
import java.nio.charset.StandardCharsets;
2021
import java.util.Arrays;
2122
import java.util.Collection;
2223
import javax.servlet.http.Cookie;
@@ -39,6 +40,7 @@
3940
* @author Rob Winch
4041
* @author Sam Brannen
4142
* @author Brian Clozel
43+
* @author Sebastien Deleuze
4244
* @since 19.02.2006
4345
*/
4446
public class MockHttpServletResponseTests {
@@ -238,10 +240,11 @@ public void servletWriterCommittedOnWriterClose() throws IOException {
238240
assertThat(response.getContentAsByteArray().length).isEqualTo(1);
239241
}
240242

241-
@Test
242-
public void servletWriterAutoFlushedForString() throws IOException {
243-
response.getWriter().write("X");
244-
assertThat(response.getContentAsString()).isEqualTo("X");
243+
@Test // gh-23219
244+
public void contentAsUtf8() throws IOException {
245+
String content = "Příliš žluťoučký kůň úpěl ďábelské ódy";
246+
response.getOutputStream().write(content.getBytes(StandardCharsets.UTF_8));
247+
assertThat(response.getContentAsString(StandardCharsets.UTF_8)).isEqualTo(content);
245248
}
246249

247250
@Test
@@ -256,6 +259,12 @@ public void servletWriterAutoFlushedForCharArray() throws IOException {
256259
assertThat(response.getContentAsString()).isEqualTo("XY");
257260
}
258261

262+
@Test
263+
public void servletWriterAutoFlushedForString() throws IOException {
264+
response.getWriter().write("X");
265+
assertThat(response.getContentAsString()).isEqualTo("X");
266+
}
267+
259268
@Test
260269
public void sendRedirect() throws IOException {
261270
String redirectUrl = "/redirect";

spring-test/src/test/java/org/springframework/test/web/servlet/result/JsonPathResultMatchersTests.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616

1717
package org.springframework.test.web.servlet.result;
1818

19+
import java.nio.charset.StandardCharsets;
20+
1921
import org.hamcrest.Matchers;
2022
import org.junit.Test;
2123

@@ -31,11 +33,13 @@
3133
* @author Craig Andrews
3234
* @author Sam Brannen
3335
* @author Brian Clozel
36+
* @author Sebastien Deleuze
3437
*/
3538
public class JsonPathResultMatchersTests {
3639

3740
private static final String RESPONSE_CONTENT = "{" + //
3841
"'str': 'foo', " + //
42+
"'utf8Str': 'Příliš', " + //
3943
"'num': 5, " + //
4044
"'bool': true, " + //
4145
"'arr': [42], " + //
@@ -51,7 +55,7 @@ public class JsonPathResultMatchersTests {
5155
try {
5256
MockHttpServletResponse response = new MockHttpServletResponse();
5357
response.addHeader("Content-Type", "application/json");
54-
response.getWriter().print(new String(RESPONSE_CONTENT.getBytes("ISO-8859-1")));
58+
response.getOutputStream().write(RESPONSE_CONTENT.getBytes(StandardCharsets.UTF_8));
5559
stubMvcResult = new StubMvcResult(null, null, null, null, null, null, response);
5660
}
5761
catch (Exception e) {
@@ -70,6 +74,11 @@ public void valueWithDirectMatch() throws Exception {
7074
new JsonPathResultMatchers("$.str").value("foo").match(stubMvcResult);
7175
}
7276

77+
@Test // gh-23219
78+
public void utf8ValueWithDirectMatch() throws Exception {
79+
new JsonPathResultMatchers("$.utf8Str").value("Příliš").match(stubMvcResult);
80+
}
81+
7382
@Test // SPR-16587
7483
public void valueWithNumberConversion() throws Exception {
7584
new JsonPathResultMatchers("$.num").value(5.0f).match(stubMvcResult);

0 commit comments

Comments
 (0)