반응형

1. 상황

Controller 단위 테스트 도중 andExpect 메서드를 사용하여 검증하는 과정에서 예외가 발생하였다.

 

2. 발생 예외

com.fasterxml.jackson.databind.exc.InvalidDefinitionException Java 8 date/time type `java.time.LocalDateTime` not supported by default: add Module "com.fasterxml.jackson.datatype:jackson-datatype-jsr310" to enable handling ...

발생한 오류 첨부

 

3. 오류 내용 분석

 예외 메시지를 보니 DTO 객체를 직렬화하는 과정에서 필드에 존재하는 `java.time.LocalDateTime` 의 데이터 타입을 지원되지 않아 처리할 수 없다는 오류였다.

 

3.1. 갑자기 웬 직렬화?

 @RestController 또는 @ResponseBody 어노테이션을 사용할 경우 리턴 값이 Json 스트링 형식으로 변환되어 응답되는데, 이때 내부 MessageConverter에 정의된 ObjectMapper에 의해 데이터가 직렬화된다. (직렬화 : Object to Json)

 반대로 @RequestBody 어노테이션을 사용할 경우 요청 Json 데이터를 Object로 변환하는데, 이때는 역직렬화 기술이 사용된다.

 

3.2. 잘못잡은 포인트

 내부 MessageConverter에서 직렬화 도중 발생한 예외인줄 알았으나, 테스트 코드의 objectMapper를 사용하여 응답 값을 검증하는 부분에서 발생했던 것이었다. ^^;;

 

private final ObjectMapper objectMapper = new ObjectMapper();
...

@Test
@TestMemberAuth
@DisplayName("채팅방 ID에 대한 채팅내역 조회")
void getChatHistory() throws Exception {
    mockMvc.perform(
                    get("/api/chatting/history/{roomId}",CHATTING_ROOM_ID_FOR_LOGIN_MEMBER_AND_VALID_MEMBER))
            .andExpect(status().isOk())
            .andExpect(content().string(objectMapper.writeValueAsString(CHATTING_HISTORY_DTO))); // 예외발생 부분
}

 

4. 해결

 테스트 코드에서 objectMapper를 생성한 이후 아래 설정을 추가하였다.

objectMapper = new ObjectMapper();
objectMapper.registerModule(new JavaTimeModule());
objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);

 위 설정은 ObjectMapper에 JavaTimeMoule을 등록한 후, 날짜와 시간을 타임스탬프로 직렬화하지 않도록 한다.

 

 참고로 예외 메시지에서 jackson-datatype-jsr310 의존을 추가하라고 하는데, spring-boot-starter-web 에 의존하는 경우 종속관계인  jackson-datatype-jsr310 도 자동 의존하는 것을 확인할 수 있었다.

 

 

 

 

 

 

 

 

 

 

 

반응형

+ Recent posts