MockMvc在Spring Boot 2.2.0中不再处理UTF-8字符。


14

在升级到新发布2.2.0.RELEASE的Spring Boot版本之后,我的一些测试失败了。似乎MediaType.APPLICATION_JSON_UTF8已弃用了,并且不再从未显式指定内容类型的控制器方法中将其作为默认内容类型返回。

测试代码如

String content = mockMvc.perform(get("/some-api")
            .contentType(MediaType.APPLICATION_JSON))
            .andExpect(status().isOk())
            .andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8))
            .andReturn()
            .getResponse()
            .getContentAsString();

突然不再工作,因为内容类型不匹配,如下所示

java.lang.AssertionError: Content type 
Expected :application/json;charset=UTF-8
Actual   :application/json

更改代码以.andExpect(content().contentType(MediaType.APPLICATION_JSON))解决此问题。

但是现在content,与预期的序列化对象进行比较时,如果对象中有任何特殊字符,则仍然不匹配。似乎.getContentAsString()默认情况下(不再)该方法不使用UTF-8字符编码。

java.lang.AssertionError: Response content expected:<[{"description":"Er hörte leise Schritte hinter sich."}]> but was:<[{"description":"Er hörte leise Schritte hinter sich."}]>
Expected :[{"description":"Er hörte leise Schritte hinter sich."}]
Actual   :[{"description":"Er hörte leise Schritte hinter sich."}]

如何获得contentUTF-8编码?

Answers:


7

是。这是从2.2.0 spring-boot起的问题。他们为默认字符集编码设置了弃用。

.getContentAsString(StandardCharsets.UTF_8) -很好,但是在任何响应中默认情况下都会填充ISO 8859-1。

在我的项目中,我更新了当前创建的转换器:

@Configuration
public class SpringConfig implements WebMvcConfigurer {

    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        converters.stream()
            .filter(converter -> converter instanceof MappingJackson2HttpMessageConverter)
            .findFirst()
            .ifPresent(converter -> ((MappingJackson2HttpMessageConverter) converter).setDefaultCharset(UTF_8));
    }
...

这是这里推荐的最简单的解决方案!
时间

你救了我的一天!
Filomat


2

从spring的5.2.0版本开始,默认编码字符不再是UTF-8。

要继续使用UTF-8,必须在MockMvc结果的ServletResponse中进行设置。要将默认字符编码设置为UTF-8,请在设置方法中执行以下操作:

@Before
public void setUp() {
   mockMvc = webAppContextSetup(wac).addFilter(((request, response, chain) -> {
                response.setCharacterEncoding("UTF-8");
                chain.doFilter(request, response);
            })).build();
}

然后,您可以使用mockMvc实例执行您的请求。

希望能有所帮助。


使用此解决方案,我将不得不在每个测试类中配置嘲笑Mvc。对于许多测试类来说,这可能是非常乏味的!
时报

0

根据这个从弹簧开发商拉入请求的UTF-8头不再需要,因此它的弃用。如果您在应用程序中使用UTF-8标头,则可以考虑将其从应用程序中删除,而不是尝试修复测试。只要确保您使用的是Content-Type:application / json标头,就可以了。


我想你不明白这个问题。我建议您阅读整个问题,然后重新评估(如果您的答案具有任何价值)。我的应用程序运行正常,问题与测试有关。
时代

我再次阅读了整个问题并重新评估了答案,答案仍然相同。在您的问题中,您不会解释为何不推荐使用标题,我在我的帖子中丰富了您的问题。我建议您阅读我链接到的PR,这样您就可以理解为什么不赞成使用标头。如果您了解原因,那么您可能要考虑更改测试,因为您的测试正在测试Spring 2.1.X中的默认行为,但是它不能正确测试Spring 2.2.X中的行为。Spring行为已更改,如果您接受新的Spring行为,则测试也应相应更改。
scre_www

您在这里不太一致。在您的答案中,您说“ [...]而不是尝试修复您的测试”。在您的评论中,您说:“如果您接受新的Spring行为,则您的测试应作相应更改。”
时报

每个程序员都时不时面对过时的值。当某个东西被弃用时,您可以以某种方式对其进行修复,而无需研究为什么它一开始就被弃用。这种方法似乎是您处理此问题的方法。现在,我建议您进一步研究一下为什么不建议使用它。如果您了解这一点,则可以对下一步做什么做出更好的决定。在您的问题中,没有任何理由说明为什么您只告诉我们您的测试由于折旧的价值而失败,这是一项糟糕的研究。我丰富了一些研究,你没有做的问题,upvoted的Q.
scre_www

0

我正在使用Spring Boot 1.5.15.RELEASE并在编写测试时遇到相同的问题。

帮助我的第一个解决方案是添加.characterEncoding(“ UTF-8”)),如下所示:

String content = mockMvc.perform(get("/some-api")
            .contentType(MediaType.APPLICATION_JSON)
            .characterEncoding("UTF-8"))
            .andExpect(status().isOk())
            .andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8))
            .andReturn()
            .getResponse()
            .getContentAsString();

我在测试类中使用了StandaloneMockMvcBuilder,因此对我有帮助的第二个解决方案是创建一个过滤器,例如:

private static class Utf8Filter extends OncePerRequestFilter {

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
        throws ServletException, IOException {
        response.setCharacterEncoding(StandardCharsets.UTF_8.toString());
        filterChain.doFilter(request, response);
    }
}

然后将其添加到我的测试类中的standaloneSetup方法中,如下所示:

@Before
public void setup() {
    MockitoAnnotations.initMocks(this);
    final SomeResource someResource = new SomeResource(someService);
    this.restLankMockMvc = MockMvcBuilders.standaloneSetup(someResource)
        .setCustomArgumentResolvers(pageableArgumentResolver)
        .setControllerAdvice(exceptionTranslator)
        .setConversionService(createFormattingConversionService())
        .setMessageConverters(jacksonMessageConverter)
        .addFilter(new Utf8Filter())
        .build();
}

0

MockMvc的附加设置.accept(MediaType.APPLICATION_JSON_UTF8_VALUE)

    String content = mockMvc.perform(get("/some-api")
        .contentType(MediaType.APPLICATION_JSON)
        .accept(MediaType.APPLICATION_JSON_UTF8_VALUE))
        .andExpect(status().isOk())
        .andExpect(content().contentType(MediaType.APPLICATION_JSON))
        .andReturn()
        .getResponse()
        .getContentAsString();

我猜这个问题不是Spring Boot,而是MockMvc特定的问题。因此,一种变通办法必须仅应用于MockMvc。(JSON必须使用UTF-8进行编码。)

相关问题:MockMvc中对JSON响应的UTF-8处理不当·问题#23622·spring-projects / spring-framework

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.