MockMvcはSpring Boot 2.2.0.RELEASEで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エンコーディングを取得するにはどうすればよいですか?

回答:


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を設定する必要があります。デフォルトの文字エンコーディングをUTF-8に設定するには、セットアップメソッドで次のようにします。

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

次に、mockMvcインスタンスを使用してリクエストを実行できます。

この助けを願っています。


このソリューションでは、すべてのテストクラスでmockMvcを構成する必要があります。これは多くのテストクラスにとって非常に退屈な作業です。
タイムズ

0

春の開発者からのこのプルリクエストによると、UTF-8ヘッダーは不要になり、非推奨になりました。アプリケーションでUTF-8ヘッダーを使用している場合は、テストを修正するのではなく、アプリケーションから削除することを検討してください。Content-Type:application / jsonヘッダーを使用していることを確認してください。問題はありません。


あなたは問題を理解していないと思います。質問全体を読んでから、再評価してみてください。もしあなたの答えが価値をもたらすなら。私のアプリケーションは完全に問題なく動作しており、問題はテストに関連しています。
タイムズ

質問全体をもう一度読み、私の答えを再評価しましたが、答えは同じです。あなたの質問では、ヘッダーが廃止された理由を説明していません。私は私の投稿で質問を充実させました。私がリンクしたPRを読むことをお勧めします。そうすれば、ヘッダーが廃止された理由を理解できます。その理由を理解している場合、テストはSpring 2.1.Xのデフォルトの動作をテストしているが、Spring 2.2.Xの動作を正しくテストしていないため、テストの変更を検討することをお勧めします。Springの動作が変更されました。新しいSpringの動作を受け入れる場合、テストはそれに応じて変更されます。
scre_www

ここでは一貫性があまりありません。あなたの答えでは、「テストを修正する代わりに[...]」と言います。コメントでは、「[...]新しいSpringの動作を受け入れた場合、テストはそれに応じて変更されるはずです」と言います。
タイムズ

すべてのプログラマーは、時々非推奨の値に直面します。何かが廃止された場合、そもそもなぜ廃止されたの調査せずに、なんとかして修正することができます。このアプローチは、この問題を処理する方法のようです。ここで、さらに詳しく調べて、なぜ非推奨になったのを調査することをお勧めします。それを理解すれば、次に何をすべきかについてより良い決定を下すことができます。あなたの質問には、研究が不十分である廃止された値のためにテストが失敗していると私たちに言う理由については何もありません。私はあなたがしなかったいくつかの調査と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を使用しているので、次のようにフィルターを作成することで、2番目の解決策が得られました。

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を使用してエンコードする必要があります。)

関連する問題:JSON応答のMockMvcでの不適切なUTF-8処理・問題#23622・spring-projects / spring-framework

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.