현재 개인 프로젝트를 진행하기 위해서 인강을 보면서 약간 의문점이 남아서 해당 부분을 기록합니다.
테스트케이스를 작성할 때
Object형태를 JSON형식으로 RequestBody에 요청하는 케이스가 생겼습니다.
아래는 위의 설명을 코드화한 것입니다.
@Test
@DisplayName("/posts 요청")
void test() throws Exception {
PostCreate request = PostCreate.builder() // 빌더패턴을 이용했습니다.
.title("제목입니다.")
.content("내용입니다.")
.build();
ObjectMapper objectMapper = new ObjectMapper(); // 오브젝트메퍼를 이용해 직렬화합니다.
String json = objectMapper.writeValueAsString(request);
mockMvc.perform(
post("/posts")
.contentType(APPLICATION_JSON)
.content(json)
)
.andExpect(status().isOk())
.andExpect(content().string("{}"))
.andDo(print());
}
생각보다 간단한 테스트 케이스입니다.
근데 여기 테스트 시 실패를 계속합니다.
cannot deserialize from Object value
이 와 같은 에러가 계속 뜨는데요 해당 부분을 검색하면
기본 생성자가 없어서 기본 생성자를 넣어줘야 한다고 합니다.
결과 적으로 아래 PostCreate라는 클래스에는 기본 생성자가 없어서 발생한 에러입니다.
@ToString
@Getter
public class PostCreate {
@NotBlank(message = "제목은 필수입니다!")
public String title;
@NotBlank(message = "내용은 필수입니다!")
public String content;
@Builder
public PostCreate(String title, String content) {
this.title = title;
this.content = content;
}
}
근데 해당 인강에서는 기본 생성자 없이 테스트가 동작이 잘 됩니다...?
뭐지...??
원인은?
ObjectMapper 이용 시 직렬화 객체에 대한 것을 모르기 때문에 발생한 것입니다.
우리는 소스를 까보면서 아 생성자에는 어떤게 있고 없고를 판단할 수 있는데 ObjectMapper는 모릅니다.
해당 내용은 이 블로그에서 정말 잘 설명해줬다
https://da-nyee.github.io/posts/woowacourse-why-the-default-constructor-is-needed/
무튼 해결 방법은?
1. 기본 생성자를 넣어준다.
@ToString
@Getter
public class PostCreate {
@NotBlank(message = "제목은 필수입니다!")
public String title;
@NotBlank(message = "내용은 필수입니다!")
public String content;
public PostCreate() {
}
@Builder
public PostCreate(String title, String content) {
this.title = title;
this.content = content;
}
}
2. @NoArgsConstructor를 달아준다 (어차피 1번의 방법을 어노테이션으로 대체한 것 뿐)
3. 기본 생성자 없이 해당 인자값을 다 지정해준다
@Builder
@JsonCreator
public PostCreate(@JsonProperty("title") String title, @JsonProperty("content") String content) {
this.title = title;
this.content = content;
}
여기서 배운 점
1) ObjectMappter는 Object to JSON 역직렬화는 setter가 없어도 된다.
왜? java reflection 패키지를 활용하기 때문에.
2) 자바 reflection은 컴파일 시점에서 객채 타입을 결정하지만 가져올 수 없는 정보 중 하나가 생성자의 인자 정보들이다.
그렇기 때문에 기본 생성자는 무조건 필수다.
3) 기본 생성자 없이 활용하는 다양한 방법들
JsonCreator를 이용한 방법, 기본 생성자를 private로 변경해 불변성을 보장하게끔 하는 방법
그리고 이 부분에 대해서는 생각보다 많은 개발자들이 선호하는게 각자 다 다른 것 같다.
무튼 해결되어 뿌듯...
하지만 뭔가 찜찜...허허..