web-dev-qa-db-ja.com

MockMvcはSpring Boot 2.2.0.RELEASEでUTF-8文字を処理しなくなりました

新しくリリースされた_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."}]
_

UTF-8エンコードでcontentを取得するにはどうすればよいですか?

14
Times

はい。これは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));
    }
...

.getContentAsString(StandardCharsets.UTF_8)の代わりに.getContentAsString()を使用すると、問題が解決します。

3
Times

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インスタンスを使用してリクエストを実行できます。

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

2
black4bird

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

0
yukihane

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

0
scre_www

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
Zuljen