需求描述
在 Junit 使用 MockMvc 对 Controller 层进行单元测试时,发现控制台打印的响应结果中文出现乱码,导致断言异常(预期值与结果不符)。
解决方案
这是由于 spring 默认字符集为 ISO-8859-1,中文无法被正确的识别。因此只要能够重新设置支持中文的字符集即可解决该问题。
修改 Servlet 配置
虽然使用 spring boot 预留的配置可以轻松的解决问题,但是粒度太粗了,一旦设置全局生效,唯一值得庆幸的是,此处需要设置的是字符集,大部分场景下都会使用 UFT-8。
1 2 3 4 5 6 7
| server: servlet: encoding: charset: UTF-8 enabled: true force-response: true
|
重写输出方法
不要使用 MockMvcResultHandlers.print()
方法输出响应结果,重新实现 ResultHandler
接口。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
| public class ForceCharsetPrintingResultHandler extends PrintingResultHandler {
private static final String DEFAULT_CHARSET = "UTF-8";
public static final ForceCharsetPrintingResultHandler UTF_8PrintingResultHandler = new ForceCharsetPrintingResultHandler(DEFAULT_CHARSET);
private final String defaultCharset;
public ForceCharsetPrintingResultHandler(String defaultCharset) { super(new ResultValuePrinter() {
@Override public void printHeading(@NotNull String heading) { System.out.println(); System.out.printf("%s:%n", heading); }
@Override public void printValue(@NotNull String label, Object value) { if (value != null && value.getClass().isArray()) { value = CollectionUtils.arrayToList(value); } System.out.printf("%17s = %s%n", label, value); }
}); this.defaultCharset = defaultCharset; }
@Override protected void printRequest(MockHttpServletRequest request) throws Exception { request.setCharacterEncoding(defaultCharset); super.printRequest(request); }
@Override protected void printResponse(MockHttpServletResponse response) throws Exception { response.setCharacterEncoding(defaultCharset); super.printResponse(response); }
}
|
1 2 3
| mockMvc.perform() .andDo(ForceCharsetPrintingResultHandler.UTF_8PrintingResultHandler)
|