인수테스트에서 응답을 역직렬화하는 과정에서 아래와 같은 예외가 발생했다.
2023-11-15 20:35:45.875 WARN 54421 --- [o-auto-1-exec-1] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.http.converter.HttpMessageNotWritableException: Could not write JSON: Cannot invoke "java.lang.Long.longValue()" because "this.tableGroupId" is null; nested exception is com.fasterxml.jackson.databind.JsonMappingException: Cannot invoke "java.lang.Long.longValue()" because "this.tableGroupId" is null (through reference chain: kitchenpos.dto.response.TableGroupResponse["orderTables"]->java.util.ArrayList[0]->kitchenpos.dto.response.OrderTableResponse["tableGroupId"])]
문제가 된 dto 의 코드.
public class OrderTableResponse {
private long id;
private Long tableGroupId;
private int numberOfGuests;
private boolean empty;
// 생략
public long getTableGroupId() {
return this.tableGroupId;
}
}
Jackson 이 직렬화 및 역직렬화하는 과정에 대한 이해부족.
Jackson 은 클래스 정보를 조사해서(클래스 파일의 멤버 필드, getter setter 메서드, 생성자 등) 프로퍼티 정보를 저장한다. 그리고 이를 기반으로 직렬화 및 역직렬화 한다. 이때 접근제어자가 public 인 경우에만 프로퍼티 정보를 저장하도록 되어있다. 따라서 문제가 발생한 dto 경우 long 타입의 tableGroupId 이름을 가진 프로퍼티 정보가 저장됨을 예상할 수 있다. 여기에 null 값 할당을 시도했기 때문에 예외가 발생한 것이다.
별다른 코드를 추가하지 않고 해결하는 방법은 두 가지가 있다.
첫 번째 멤버 필드의 접근제어자를 public 으로 넓힌다.
두 번째 getter 메서드의 반환 타입을 Long 타입으로 수정한다.
멤버 필드의 외부 접근을 허용하면 부수 작용이 발생할 수 있으므로 두 번째 해결 방법을 선택했다.
public class OrderTableResponse {
private long id;
private Long tableGroupId;
private int numberOfGuests;
private boolean empty;
// 생략
public Long getTableGroupId() {
return this.tableGroupId;
}
}