From 5fb58e51e5d58da884499197928b2a4447b47033 Mon Sep 17 00:00:00 2001 From: Sam Brannen Date: Wed, 12 Jan 2022 17:07:45 +0100 Subject: [PATCH] Infer UTF-8 encoding for JSON response with MockMvc's andDo(print(...)) Prior to this commit, the PrintingResultHandler in MockMvc -- typically invoked via .andDo(print()) -- printed an `application/json` response body using the default encoding (ISO-8859-1), which resulted in UTF-8 characters being garbled. Since an `application/json` response is implicitly encoded using UTF-8, the PrintingResultHandler now infers UTF-8 encoding for such response bodies. Closes gh-27926 --- .../servlet/result/PrintingResultHandler.java | 8 ++++-- ...PrintingResultHandlerIntegrationTests.java | 25 ++++++++++++++++++- 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/spring-test/src/main/java/org/springframework/test/web/servlet/result/PrintingResultHandler.java b/spring-test/src/main/java/org/springframework/test/web/servlet/result/PrintingResultHandler.java index f0ea1c5b658..aae8c3d7254 100644 --- a/spring-test/src/main/java/org/springframework/test/web/servlet/result/PrintingResultHandler.java +++ b/spring-test/src/main/java/org/springframework/test/web/servlet/result/PrintingResultHandler.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2021 the original author or authors. + * Copyright 2002-2022 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,6 +16,7 @@ package org.springframework.test.web.servlet.result; +import java.nio.charset.StandardCharsets; import java.util.Collections; import java.util.Enumeration; import java.util.Map; @@ -27,6 +28,7 @@ import javax.servlet.http.HttpSession; import org.springframework.core.style.ToStringCreator; import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; import org.springframework.lang.Nullable; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletResponse; @@ -249,7 +251,9 @@ public class PrintingResultHandler implements ResultHandler { this.printer.printValue("Error message", response.getErrorMessage()); this.printer.printValue("Headers", getResponseHeaders(response)); this.printer.printValue("Content type", response.getContentType()); - this.printer.printValue("Body", response.getContentAsString()); + String body = (MediaType.APPLICATION_JSON_VALUE.equals(response.getContentType()) ? + response.getContentAsString(StandardCharsets.UTF_8) : response.getContentAsString()); + this.printer.printValue("Body", body); this.printer.printValue("Forwarded URL", response.getForwardedUrl()); this.printer.printValue("Redirected URL", response.getRedirectedUrl()); printCookies(response.getCookies()); diff --git a/spring-test/src/test/java/org/springframework/test/web/servlet/samples/standalone/resulthandlers/PrintingResultHandlerIntegrationTests.java b/spring-test/src/test/java/org/springframework/test/web/servlet/samples/standalone/resulthandlers/PrintingResultHandlerIntegrationTests.java index 9d47134e0fb..21822d73176 100644 --- a/spring-test/src/test/java/org/springframework/test/web/servlet/samples/standalone/resulthandlers/PrintingResultHandlerIntegrationTests.java +++ b/spring-test/src/test/java/org/springframework/test/web/servlet/samples/standalone/resulthandlers/PrintingResultHandlerIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2021 the original author or authors. + * Copyright 2002-2022 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,10 +23,12 @@ import javax.servlet.http.HttpServletResponse; import org.junit.jupiter.api.Test; +import org.springframework.http.MediaType; import org.springframework.test.web.servlet.result.PrintingResultHandler; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; +import static java.nio.charset.StandardCharsets.UTF_8; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.fail; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; @@ -61,6 +63,22 @@ class PrintingResultHandlerIntegrationTests { .contains("Headers = [Set-Cookie:\"enigma=42\", Content-Type:\"text/plain;charset=ISO-8859-1\", Content-Length:\"14\"]"); } + @Test + void printMvcResultsToWriterWithJsonResponseBodyInterpretedAsUtf8() throws Exception { + StringWriter writer = new StringWriter(); + + standaloneSetup(new SimpleController()).build() + // "Hallöchen" is German slang for "hello". + .perform(get("/utf8").accept(MediaType.APPLICATION_JSON).content("Hallöchen, Welt!".getBytes()).characterEncoding(UTF_8)) + .andDo(print(writer)) + // "Grüß dich!" is German for "greetings to you". + .andExpect(content().bytes("Grüß dich!".getBytes())); + + assertThat(writer).asString() + .contains("Body = Hallöchen, Welt!") + .contains("Body = Grüß dich!"); + } + @Test void printMvcResultsToWriterWithFailingGlobalResultMatcher() throws Exception { StringWriter writer = new StringWriter(); @@ -92,6 +110,11 @@ class PrintingResultHandlerIntegrationTests { response.addCookie(new Cookie("enigma", "42")); return "Hello Response"; } + + @GetMapping("/utf8") + String utf8(HttpServletResponse response) { + return "Grüß dich!"; + } } }