테스트 코드를 작성하면서 VO 클래스를 기본 생성자로 만들어주고 setter 메서드로 필요한 속성에 값을 넣어서 사용했다. 하지만 프로젝트를 리뷰해주시는 선배님의 조언으로 @Builder 어노테이션을 사용해보는 게 어떻겠냐는 말에 @Builder 어노테이션을 사용한 후기와 그 과정에서 발생한 에러를 어떻게 해결했는지 기록하기 위해 포스팅을 하게 되었다.
▷ Message.java
@Data
@Builder
public class Message {
private int mesNo;
private String mesCon;
private Date createdAt;
private String sendId;
private String recvId;
private String isShow;
}
기본적으로 @Data 어노테이션을 사용했고 @Builder 어노테이션을 추가해주었다.
@SpringBootTest
public class MessageTest {
@Autowired
private MessageService messageService;
// @Builder 적용 전
@Test
public void 쪽지_보내기(){
//given
Message message = new Message();
message.setMesCon("안녕하세요.");
message.setRecvId("ckdrl");
message.setSendId("wodud");
message.setMesNo(1);
message.setIsShow("Y");
//when
messageService.sendMessage(message);
List<Message> messages = messageService.selectMessages(message);
//then
assertThat(messages.size()).isEqualTo(1);
}
// @Builder 적용 후
@Test
public void 쪽지_보내기(){
//given
Message message = Message.builder()
.mesCon("안녕하세요.")
.recvId("ckdrl")
.sendId("wodud")
.mesNo(1)
.isShow("Y")
.build();
//when
messageService.sendMessage(message);
List<Message> messages = messageService.selectMessages(message);
//then
assertThat(messages.size()).isEqualTo(1);
}
}
위 코드를 보면 @Builder 어노테이션을 적용 전/후의 차이를 한눈에 볼 수 있다. 일단 반복적으로 타이핑을 하는 수고가 줄었다. 그리고 가독성도 좋아진 것을 볼 수 있다.
작성한 코드를 테스트해보면 아래와 같은 결과가 나온다.
org.springframework.jdbc.UncategorizedSQLException: Error attempting to get column 'SENDID' from result set. Cause: java.sql.SQLException: 부적합한 변환이 요청됨;
uncategorized SQLException; SQL state [99999]; error code [17132]; 부적합한 변환이 요청됨;
nested exception is java.sql.SQLException: 부적합한 변환이 요청됨
그렇다... 에러가 발생했다. 당연히 성공할 줄 알았는데 보기 좋게 실패했다. 해당 에러를 구글링에서 찾아서 시도해보았지만 만족스러운 결과를 얻지 못했다. 그러다 @Data과 @Builder에 대해 놓친 부분을 찾아보면 실마리를 얻을 수 있을 거라고 생각하여 검색하기 시작했다.
@Builder 어노테이션은 2가지 방법으로 사용할 수 있는데
첫째는 필자가 사용한 것처럼 클래스 위에 @Builder 어노테이션을 붙여서 사용하는 방법과
둘째는 클래스 내에 생성자 함수를 만들고 그 생성자 함수에 @Builder 어노테이션을 붙이는 방법이다.
@Builder는 클래스 내에 기본 생성자든, 특정 매개변수를 받는 생성자든 , 모든 변수를 받는 생성자든 정의한 생성자가 있는 상황에 @Builder가 붙은 생성자를 사용하게 된다.
첫 번째 방법을 사용할 경우 생성자 함수가 없으면 Lombok은 모든 변수를 받는 생성자를 Builder로 사용하는데 필자가 작성한 코드에는 모든 변수를 받는 생성자가 없기 때문에 에러가 발생한 것이다. 그래서 아래와 같이 생성자를 만들어주면 테스트는 성공적으로 끝나게 된다.
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Message {
private int mesNo;
private String mesCon;
private Date createdAt;
private String sendId;
private String recvId;
private String isShow;
}
두 번째 방법을 사용할 경우 특정 변수를 받는 생성자를 생성하고 그 위에 @Builder를 붙여주면 된다.
@Data
public class Message {
private int mesNo;
private String mesCon;
private Date createdAt;
private String sendId;
private String recvId;
private String isShow;
@Builder
public Message(int mesNo, String mesCon, String sendId, String recvId,String isShow){
this.mesNo = mesNo;
this.mesCon = mesCon;
this.sendId = sendId;
this.recvId = recvId;
this.isShow = isShow;
}
}
그러면 첫 번째 방법과 마찬가지로 성공적으로 테스트를 마치게 된다.
※ 정리
@Builder는 클래스 위에 선언해서 사용하는 방법과 클래스 내에 생성자 함수에 선언해서 사용하는 방법 두 가지가 있다.
전자를 사용할 경우 아무 생성자도 선언되어 있지 않으면 Lombok은 모든 변수를 받는 생성자를 호출하게 되므로 @AllArgsConstructor 어노테이션을 이용하거나 전체 변수를 갖는 생성자를 만들어주면 된다.
후자를 사용할 경우 클래스 내에 특정 생성자를 만들어주고 그 위에 @Builder 어노테이션을 선언해주면 된다.
+ 추가
@Data
public class Message {
private int mesNo;
private String mesCon;
private Date createdAt;
private String sendId;
private String recvId;
private String isShow;
@Builder
public Message(int mesNo, String mesCon, String sendId, String recvId,String isShow){
this.mesNo = mesNo;
this.mesCon = mesCon;
this.sendId = sendId;
this.recvId = recvId;
this.isShow = isShow;
}
}
@NoArgsConstructor와 @AllArgsConstrutor를 추가해주지 않고 했을 때, 테스트 코드는 잘 수행됐지만 통합 테스트에서는 에러가 발생했다. 그래서 @NoArgsConstructor와 @AllArgsConstrutor를 추가해주지 않아서 생긴 문제인 거 같아서 추가해주었더니 통합 테스트도 정상적으로 진행할 수 있게 되었다.
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Message {
private Integer mesNo;
private String mesCon;
private Date createdAt;
private String sendId;
private String recvId;
private String isShow;
@Builder
public Message(Integer mesNo, String mesCon, String sendId, String recvId,String isShow){
this.mesNo = mesNo;
this.mesCon = mesCon;
this.sendId = sendId;
this.recvId = recvId;
this.isShow = isShow;
}
}
※ 도움을 주신 분
'Hi Planner' 카테고리의 다른 글
[Hi Planner] 메시지 가져오기(All elements are null 해결) (0) | 2022.05.29 |
---|---|
[Hi Planner] 다른 일정 조회하기. (0) | 2022.05.26 |
[Hi Planner] login 화면 (0) | 2022.05.21 |
[intelliJ + gradle + spring boot] 오라클 연동과 마이바티스 의존성 추가 (0) | 2022.05.13 |
[intelliJ + gradle + spring boot] JSP 프로젝트 시작하기 (HiPlanner) (0) | 2022.05.13 |