@Test
@DisplayName("201 코드를 반환한다")
void it_responses_201() throws Exception {
mockMvc.perform(
post("/products")
.contentType(MediaType.APPLICATION_JSON)
.content(JsonUtil.writeValue(TOY_1.요청_데이터_생성()))
)
.andExpect(status().isCreated())
.andExpect(content().string(containsString(TOY_1.NAME())))
.andExpect(content().string(containsString(TOY_1.MAKER())));
}
// TOY_1.요청_데이터_생성() 내부로직
ProductRequest.builder()
.name(name)
.maker(maker)
.price(price)
.imageUrl(imageUrl)
.build();
위 코드에서 .content(JsonUtil.writeValue(TOY_1.요청_데이터_생성()))
를 통해 테스트 데이터를 집어넣고 반환하는 과정에서 반환된 데이터의 한글 값들이 깨지는 현상
반환된 데이터가 깨져있기 때문에 아래의 .andExpect(content().string(containsString("범냐옹")))
검증 구문에서 “범냐옹”이 포함된 문자가 존재하지 않아 검증 실패
APPLICATION_JSON_UTF8
)는 @Deprecated
되어있는 상태.[Why?]
Public constant media type for application/json;charset=UTF-8.
Deprecated : as of 5.2 in favor of APPLICATION_JSON since major browsers like Chrome now comply with the specification and interpret correctly UTF-8 special characters without requiring a charset=UTF-8 parameter.
Chrome과 같은 주요 브라우저에서는 이전과 다르게 이제는 사양을 준수하기 때문에, charset=UTF-8
매개변수 없이도 UTF-8 특수문자를 제대로 해석할 수 있다고 한다.
또한 위와 같은 이유로 Spring에서는 더 이상 charset 부분을 사용하지 않는다는 목적을 가지게 되었다고 한다.
따라서 charset을 사용하지 않으니 자연스럽게 MediaType.APPLICATION_JSON_UTF8
의 사용 중단(Deprecated)을 결정하고 MediaType.APPLICATION_JSON
사용을 권장하는것 같다.
MediaType.APPLICATION_JSON_UTF8
는 내부에 2개의 속성을 가지고 있음해당 결정은 Spring 5.2(Boot 2.2) 버전부터 적용된 것으로 보인다.
WebMvcConfigurer
를 구현하여 메시지 컨버터 중에 MappingJackson2HttpMessageConverter
일 때 setDefaultCharset(UTF_8));
설정을 통해 charset을 설정해주는 방법이다.MappingJackson2HttpMessageConverter
가 DTO 객체에 데이터를 매핑해주는 역할을 해준다.아래 대댓글을 보면 이 방법은 곧 Header에 application/json;charset=UTF-8
설정을 하는 것이나 다름 없으니 Spring의 본래 목적(charset 미사용)을 무효화 시킨다고 한다.
따라서 테스트 값 자체를 수정하는 것이 좋지 않겠냐고 제안한다.
해당 대댓글의 의견에 공감이 되었으므로 나는 아래와 같이 구현함으로써 문제를 해결하였다.
import org.springframework.boot.test.autoconfigure.web.servlet.MockMvcBuilderCustomizer;
import org.springframework.stereotype.Component;
import org.springframework.test.web.servlet.setup.ConfigurableMockMvcBuilder;
import java.nio.charset.StandardCharsets;
// @AutoconfigureMockMvc를 사용하여 MockMvc를 주입하는 경우에 한해서만 적용
@Component
class MockMvcCharacterEncodingCustomizer implements MockMvcBuilderCustomizer {
@Override
public void customize(ConfigurableMockMvcBuilder<?> builder) {
builder.alwaysDo(result -> result.getResponse().setCharacterEncoding(StandardCharsets.UTF_8.name()));
}
}
위와 같이 적용할 경우 MockMvc의 테스트 결과 값의 문자를 UTF-8로 세팅하여 한글이 깨지지 않아 정상적으로 테스트 검증을 할 수 있다.
덕분에 좋은 내용 잘 보고 갑니다.
정말 감사합니다.