Skip to content

Commit

Permalink
Improve charset handling in MockHttpServletResponse
Browse files Browse the repository at this point in the history
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
  • Loading branch information
sdeleuze committed Jul 16, 2019
1 parent 60a7092 commit adadffe
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import java.nio.charset.Charset;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
Expand Down Expand Up @@ -204,11 +205,32 @@ public byte[] getContentAsByteArray() {
return this.content.toByteArray();
}

/**
* Get the content of the response body as a {@code String}, using the configured
* {@linkplain #getCharacterEncoding character encoding}.
* @return the content as a {@code String}
* @throws UnsupportedEncodingException if the character encoding is not supported
* @see #getContentAsString(Charset)
*/
public String getContentAsString() throws UnsupportedEncodingException {
return (this.characterEncoding != null ?
this.content.toString(this.characterEncoding) : this.content.toString());
}

/**
* Get the content of the response body as a {@code String}, using the provided
* {@code fallbackCharset} if no charset has been explicitly defined, else using
* using the configured {@linkplain #getCharacterEncoding character encoding}.
* @return the content as a {@code String}
* @throws UnsupportedEncodingException if the character encoding is not supported
* @see #getContentAsString()
*/
public String getContentAsString(Charset fallbackCharset) throws UnsupportedEncodingException {
return isCharset() ?
this.content.toString(this.characterEncoding) :
this.content.toString(fallbackCharset.name());
}

@Override
public void setContentLength(int contentLength) {
this.contentLength = contentLength;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package org.springframework.test.web.servlet.result;

import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;

import com.jayway.jsonpath.JsonPath;
import org.hamcrest.Matcher;
Expand Down Expand Up @@ -235,7 +236,7 @@ public ResultMatcher isMap() {
}

private String getContent(MvcResult result) throws UnsupportedEncodingException {
String content = result.getResponse().getContentAsString();
String content = result.getResponse().getContentAsString(StandardCharsets.UTF_8);
if (StringUtils.hasLength(this.prefix)) {
try {
String reason = String.format("Expected a JSON payload prefixed with \"%s\" but found: %s",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package org.springframework.mock.web;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Collection;
import javax.servlet.http.Cookie;
Expand All @@ -39,6 +40,7 @@
* @author Rob Winch
* @author Sam Brannen
* @author Brian Clozel
* @author Sebastien Deleuze
* @since 19.02.2006
*/
public class MockHttpServletResponseTests {
Expand Down Expand Up @@ -238,10 +240,11 @@ public void servletWriterCommittedOnWriterClose() throws IOException {
assertThat(response.getContentAsByteArray().length).isEqualTo(1);
}

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

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

@Test
public void servletWriterAutoFlushedForString() throws IOException {
response.getWriter().write("X");
assertThat(response.getContentAsString()).isEqualTo("X");
}

@Test
public void sendRedirect() throws IOException {
String redirectUrl = "/redirect";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@

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

import java.nio.charset.StandardCharsets;

import org.hamcrest.Matchers;
import org.junit.Test;

Expand All @@ -31,11 +33,13 @@
* @author Craig Andrews
* @author Sam Brannen
* @author Brian Clozel
* @author Sebastien Deleuze
*/
public class JsonPathResultMatchersTests {

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

@Test // gh-23219
public void utf8ValueWithDirectMatch() throws Exception {
new JsonPathResultMatchers("$.utf8Str").value("Příliš").match(stubMvcResult);
}

@Test // SPR-16587
public void valueWithNumberConversion() throws Exception {
new JsonPathResultMatchers("$.num").value(5.0f).match(stubMvcResult);
Expand Down

1 comment on commit adadffe

@sbrannen
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

Please sign in to comment.