MockMvc verarbeitet mit Spring Boot 2.2.0.RELEASE keine UTF-8-Zeichen mehr


14

Nach dem Upgrade auf die neu veröffentlichte 2.2.0.RELEASEVersion von Spring Boot sind einige meiner Tests fehlgeschlagen. Es scheint, dass der MediaType.APPLICATION_JSON_UTF8veraltet ist und nicht mehr als Standardinhaltstyp von Controller-Methoden zurückgegeben wird, die den Inhaltstyp nicht explizit angeben.

Testcode wie

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

funktionierte plötzlich nicht mehr, da der Inhaltstyp wie unten gezeigt nicht übereinstimmte

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

Ändern Sie den Code, .andExpect(content().contentType(MediaType.APPLICATION_JSON))um das Problem vorerst zu beheben.

Beim Vergleich contentmit dem erwarteten serialisierten Objekt besteht jedoch immer noch eine Nichtübereinstimmung, wenn das Objekt Sonderzeichen enthält. Es scheint, dass die .getContentAsString()Methode standardmäßig nicht mehr die UTF-8-Zeichencodierung verwendet (mehr).

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."}]

Wie komme ich contentzur UTF-8-Codierung?

Antworten:


7

Ja. Dies ist ein Problem von 2.2.0 Spring-Boot. Sie legen die Verachtung für die Standardzeichensatzcodierung fest.

.getContentAsString(StandardCharsets.UTF_8) - gut, aber in jeder Antwort wird standardmäßig ISO 8859-1 ausgefüllt.

In meinem Projekt habe ich den aktuell erstellten Konverter aktualisiert:

@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));
    }
...

Dies war die einfachste hier empfohlene Lösung!
Zeiten

du hast meinen Tag gerettet!
Filomat


2

Das Standardcodierungszeichen ist seit der Version 5.2.0 von Spring nicht mehr UTF-8.

Um UTF-8 weiterhin verwenden zu können, müssen Sie es in der ServletResponse des MockMvc-Ergebnisses festlegen. Führen Sie in Ihrer Setup-Methode Folgendes aus, um die Standardzeichencodierung auf UTF-8 festzulegen:

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

Anschließend können Sie die mockMvc-Instanz verwenden, um Ihre Anforderung auszuführen.

Ich hoffe das hilft.


Mit dieser Lösung müsste ich das mockMvc in jeder Testklasse konfigurieren. Dies kann für viele Testklassen ziemlich mühsam sein!
Zeiten

0

Gemäß dieser Pull-Anfrage der Federentwickler wird der UTF-8-Header nicht mehr benötigt und ist daher veraltet. Wenn Sie den UTF-8-Header in Ihrer Anwendung verwenden, können Sie ihn aus Ihrer Anwendung entfernen, anstatt zu versuchen, Ihren Test zu reparieren. Stellen Sie einfach sicher, dass Sie den Header Content-Type: application / json verwenden, und es sollte Ihnen gut gehen.


Ich denke, Sie verstehen das Problem nicht. Ich schlage vor, Sie lesen die gesamte Frage und bewerten sie erneut, wenn Ihre Antwort einen Wert liefert. Meine Bewerbung funktioniert einwandfrei, das Problem hängt mit den Tests zusammen.
Zeiten

Ich habe die ganze Frage noch einmal gelesen und meine Antwort neu bewertet. Die Antwort ist immer noch dieselbe. In Ihrer Frage erklären Sie nicht, warum der Header veraltet ist. Ich habe Ihre Frage mit meinem Beitrag angereichert. Ich schlage vor, Sie lesen die PR, auf die ich verlinkt habe, damit Sie verstehen, warum der Header veraltet ist. Wenn Sie das Warum verstehen, sollten Sie Ihren Test ändern, da Ihr Test das Standardverhalten in Spring 2.1.X testet, das Verhalten in Spring 2.2.X jedoch nicht korrekt testet. Das Federverhalten hat sich geändert. Ihr Test sollte sich entsprechend ändern, wenn Sie das neue Federverhalten akzeptieren.
scre_www

Sie sind hier nicht sehr konsequent. In Ihrer Antwort sagen Sie "[...] anstatt zu versuchen, Ihren Test zu reparieren". In Ihrem Kommentar sagen Sie: "[...] Ihr Test sollte sich entsprechend ändern, wenn Sie das neue Spring-Verhalten akzeptieren."
Zeiten

Jeder Programmierer sieht sich hin und wieder mit veralteten Werten konfrontiert. Wenn etwas veraltet ist, können Sie es irgendwie beheben, ohne zu untersuchen, warum es überhaupt veraltet ist. Dieser Ansatz scheint die Art zu sein, wie Sie mit diesem Problem umgehen. Jetzt schlage ich vor, Sie schauen weiter und recherchieren, warum es veraltet ist. Wenn Sie das verstehen, können Sie eine bessere Entscheidung treffen, was als nächstes zu tun ist. In Ihrer Frage gibt es nichts darüber, warum Sie uns nur mitteilen, dass Ihr Test aufgrund eines veralteten Werts, der eine schlechte Forschung darstellt, fehlschlägt. Ich habe die Frage mit einigen Nachforschungen bereichert, die Sie nicht durchgeführt haben, UND das Q.
scre_www

0

Ich verwende Spring Boot 1.5.15.RELEASE und habe beim Schreiben von Tests das gleiche Problem festgestellt.

Die erste Lösung, die mir geholfen hat, war das Hinzufügen von .characterEncoding ("UTF-8")) wie folgt:

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();

Ich verwende einen StandaloneMockMvcBuilder in meiner Testklasse. Die zweite Lösung, die mir geholfen hat, war das Erstellen eines Filters, z.

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);
    }
}

und später zur StandaloneSetup-Methode in meiner Testklasse wie folgt hinzufügen:

@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

Zusätzliche Einstellung zu 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();

Dieses Problem ist nicht Spring Boot, sondern MockMvc-spezifisch, denke ich. Daher muss eine Problemumgehung nur auf MockMvc angewendet werden. ( JSON muss mit UTF-8 codiert werden .)

Zugehöriges Problem: Unsachgemäße UTF-8-Behandlung in MockMvc für JSON-Antwort · Problem Nr. 23622 · Spring-Projekte / Spring-Framework

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.