이번 미션에서 MockMvc를 이용하여 컨트롤러 테스트를 진행하던 중 아래와 같은 예외를 볼 수 있었습니다.
@DisplayName("진행 중인 모든 방을 찾아온다.")
@Test
void findRooms() throws Exception {
RoomsResponseDto roomsResponseDto = RoomsResponseDto.of(List.of(createRoomEntity(1L)
, createRoomEntity(2L)));
String response = objectMapper.writeValueAsString(roomsResponseDto);
given(chessService.findRooms())
.willReturn(roomsResponseDto);
mockMvc.perform(get(DEFAULT_API))
.andExpect(status().isOk())
.andExpect(content().string(response));
}
그 이유는 Spring 5.2.0 버전부터 더이상 UTF-8로 기본 인코딩 캐릭터를 제공하지 않기 때문인데요.
웹 요청에서는 UTF-8 설정을 하지 않더라도 한글이 깨지는 현상이 없지만, MockMvc를 이용하여 테스트 하기 위해서는 테스트용 기본 인코딩 캐릭터를 UTF-8로 변경해야 합니다.
문제점을 탐색하고, 해당 문제만 해결할 수 있는 방법을 알아보겠습니다.
1. @RequestMapping 의 produce 키워드
첫 번째로 시도한 방법은 produce 키워드를 이용해 메서드 자체에서 캐릭터 셋을 설정하는 방법이었습니다.
@GetMapping(produce = "application/json; charset=utf-8" )
해당 방법을 통해 문제를 해결할 수 있었지만 매 코드마다 반환하는 charset을 지정해줘야 한다는 측면에서 이 문제를 해결하기 위한 적절한 방법은 아니었습니다.
2. 프로그램 전체 MessageConverter 설정 변경
두 번째로 시도한 방법은 프로그램 전체 MessageConverter 기본 charSet을 UTF-8로 변경하는 것이었습니다.
전체 설정을 커스텀하여 사용하는 방법 중에는 @Bean을 이용한 의존성 주입도 있지만 스프링의 WebMvcConfigurer에 존재하는 MessageConverter를 커스텀하여 사용할 수도 있습니다.
@Configuration
public class WebConfig implements WebMvcConfigurer {
// 1번 방법 - responseHeader의 반환 medialType을 Json utf-8로 설정한다.
@Override
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
configurer.defaultContentType(MediaType.APPLICATION_JSON_UTF8);
}
// 2번 방법 - Json으로 변환해주는 MappingJackson2HttpMessageConverter의 설정을 UTF-8로 변경한다.
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.stream()
.filter(converter -> converter instanceof MappingJackson2HttpMessageConverter)
.findFirst()
.ifPresent(converter -> ((MappingJackson2HttpMessageConverter) converter).setDefaultCharset(UTF_8));
}
}
하지만 위 두가지 방법 또한 테스트 코드에서 반환되는 response만 수정하는 방법이 아니기 때문에 이 문제의 해결방법과는 거리가 있습니다.
3. MockMvc custom
현재 저의 컨트롤러 테스트 코드는 컨텍스트에 컨트롤러를 캐싱하고 @Autowired 키워드를 통해 MockMvc를 주입받는 형태입니다.
@WebMvcTest(ChessController.class)
class ChessControllerTest {
@Autowired
private MockMvc mockMvc;
}
따라서 MockMvcBuilder를 이용한 filter 설정이 어렵습니다. 하지만 @Autowired를 사용할 수 있다는 것은 스프링에서 제공하는 기본 MockMvc를 커스텀하여 사용할 수 있다는 뜻입니다.
public class MockMvcConfig implements MockMvcBuilderCustomizer {
@Override
public void customize(ConfigurableMockMvcBuilder<?> builder) {
builder.alwaysDo(result -> result.getResponse().setCharacterEncoding("UTF-8"));
}
}
위 코드처럼 MockMvcBuilderCustomizer
를 상속받아 result
의 기본 인코딩은 UTF-8로 설정하여 MockMvc의 기본 설정을 커스터마이징합니다.
그리고 사용하고자 하는 테스트 코드에서 해당 코드를 @Import하여 사용합니다.
@Import(MockMvcConfig.class)
@WebMvcTest(ChessController.class)
class ChessControllerTest {
@Autowired
private MockMvc mockMvc;
}
이제 기존에 인코딩 이슈로 실패했던 테스트 코드를 돌려보면 아래와 같이 테스트를 성공합니다.
'우아한테크코스 4기 > 레벨2' 카테고리의 다른 글
[SQL] 페이징 구현하기 (2) | 2022.05.07 |
---|---|
[Spring] Transaction 추상화, 동기화 (0) | 2022.04.27 |
[Spring] MockMvc 를 이용한 컨트롤러 테스트 (0) | 2022.04.23 |
[Spring] NamedParameterJdbcTemplate 사용하기 (4) | 2022.04.21 |
[Spring] Spring Boot에서 트랜잭션 사용하기 (1) | 2022.04.20 |