[내일배움캠프] 3월 2일 목요일 TIL 회고록
오늘 배운 것 : 테스트 코드 작성
Querydsl은 잠시 미루고 더 급한 테스트 코드를 작성했다.
원래 Mockito를 사용하여 테스트 코드를 작성하려고 했는데 유저의 이름을 가져오는 부분에서 막혀서..
결국 Mockito를 사용하지 않고 테스트 코드를 작성했다.
스프링부트로 테스트를 할 것이므로 @SpringBootTest 를 사용했다.
@SpringBootTest
class CommentServiceImplTest {
@BeforeEach 를 사용해서 테스트 메서드 실행 이전에 수행되도록 만들었다.
@BeforeEach
public void beforeEach() throws IOException {
Long questionBoardId = 1L;
Long communityBoardId = 2L;
// 질문 댓글 작성 요청
CommentRequest request = new CommentRequest("질문댓글");
// 잡담 댓글 작성 요청
CommentRequest request2 = new CommentRequest("잡담댓글");
// findById를 사용해서 1번 유저 저장
Optional<User> findUser = userRepository.findById(1L);
// 질문 댓글 작성
commentService.createQuestionComment(questionBoardId, request, findUser.get());
// 잡담 댓글 작성
commentService.createCommunityComment(communityBoardId, request2, findUser.get());
}
먼저 질문 댓글 작성 테스트 메서드를 만들었다.
// 질문 댓글 작성
@Test
@DisplayName("질문 댓글 작성")
void createQuestionComment() {
// given
// 질문 댓글 작성 요청
CommentRequest request = new CommentRequest("질문댓글");
// 질문 게시글은 1번으로 선언
Long questionBoardId = 1L;
// findById를 사용해서 1번 유저 저장
Optional<User> findUser = userRepository.findById(1L);
// when
// 질문 댓글 작성 ("질문댓글")
commentService.createQuestionComment(questionBoardId, request, findUser.get());
// findById를 사용해서 1번 유저 저장(BeforeEach 메서드에서 만든 댓글)
Optional<Comment> findComment = commentRepository.findById(1L);
// then
// request.genContent() = "질문댓글" 이랑
// findComment.get().getContent() = "질문댓글" 이랑 같은지 확인
assertThat(request.getContent()).isEqualTo(findComment.get().getContent());
}
실행 결과

질문 댓글을 수정하는 기능 테스트 메서드를 만들어봤다.
@Test
@DisplayName("질문 댓글 수정")
void updateQuestionComment() {
// given
// findById로 1번 유저 저장
Optional<User> findUser = userRepository.findById(1L);
// 질문 댓글 작성 요청("질문댓글수정")
CommentRequest commentRequest = new CommentRequest("질문댓글수정");
// when
// 질문 댓글 업데이트 ("질문댓글" 에서 "질문댓글수정" 으로)
commentService.updateQuestionComment(1L, commentRequest, findUser.get());
// findById를 사용해서 1번 댓글 저장(위에 기능때문에 댓글 내용이 "질문댓글수정"으로 변함
Optional<Comment> questionComment = commentRepository.findById(1L);
// then
// questionComment.get().getContent() = "질문댓글수정" 이랑
// commentRequest.getContent() = "질문댓글수정" 이랑 같은지 확인하는 기능
assertThat(questionComment.get().getContent()).isEqualTo(commentRequest.getContent());
}
실행 결과
질문 삭제 기능 테스트 메서드도 만들었다.
@Test
@DisplayName("질문 댓글 삭제")
void deleteQuestionComment() {
// given
// findById를 사용해서 1번 유저 저장
Optional<User> findUser = userRepository.findById(1L);
// findById를 사용해서 1번 질문 댓글 저장
Optional<Comment> findComment = commentRepository.findById(1L);
// when
// 1번 댓글을 지우는 기능
commentService.deleteQuestionComment(1L, findUser.get());
// then
// commentRepository.existCommentById를 사용해서 1번 댓글이 있는지 확인한다.
// 그리고 isFalse()를 사용해서 댓글이 없는지 확인한다.
assertThat(commentRepository.existsCommentById(1L)).isFalse();
}
실헹 결과
잡담 댓글 작성/수정/삭제도 위에 코드랑 일치해서 패스!
내가 쓴 댓글 조회 기능 테스트 메서드도 만들었는데 이렇게 만드는게 맞는지 애매하다.
@Test
@DisplayName("내가 쓴 댓글 조회")
void getMyComments() {
// given
// 페이징 처리 기능이 있는 CommentList 생성자를 불러온다.
CommentList commentList = new CommentList();
// findById를 사용해서 1번 유저를 저장
Optional<User> findUser = userRepository.findById(1L);
// findById를 사용해서 1번 댓글을 저장
Optional<Comment> findComment = commentRepository.findById(1L);
// when
// getMyComments를 사용해서 내가 쓴 댓글 조회 (페이징 처리)
commentService.getMyComments(commentList, findUser.get().getId(), findUser.get());
// then
// 여기서 생각을 되게 많이했는데.. 이게 맞는지 모르겠다.
assertThat(commentList.toPageable()).isNotNull();
}
마지막 then에 검증을 하는 부분을 어떻게 해야할지 모르겠다.. ㅠㅠ 일단 저렇게 하면 테스트 성공이 나오긴 하는데.. 내일 물어봐야겠다.
아직 문제가 있다.. 테스트를 단건으로 실행하면 다 통과하는데 한꺼번에 실행하면 에러가 난다.
이렇게..
내일 고쳐봐야겠다.. 테스트 코드 작성하는건 너무 재밌는데 저렇게 빨간색이 뜨면 참.. 기분이 묘하다 ㅋㅋㅋ
테스트 코드를 구현하기 전에 api가 잘 동작하는지 테스트를 하려고 했는데 댓글 작성을 하면
이런식으로 Postman에서 오류를 뱉어내면서 작성, 수정이 전부 안됐다.
JSON parse error:
Cannot construct instance of `com.example.lomboktest.SampleDto`
(although at least one Creator exists):
cannot deserialize from Object value (no delegate- or property-based Creator);
Controller단에 RequestParam 문제인 것 같아 이름을 바꿔주어도 똑같이 오류가 발생했다.
구글링을 해보니 @Bulider 어노테이션 사용으로 인해서 해당 오류가 날 수도 있다고 적혀있었다.
생각해보니 테스트 코드를 만들때 Builder 를 사용해서 생성자를 만들려고 했었다. 그래서 requestDto를 보니
@Builder 어노테이션이 붙어있었다.
@Getter
@Builder
public class CommentRequest {
private String content;
}
그래서 Builder 어노테이션을 없애고 생성자를 추가해주는 어노테이션을 추가했다.
추가한 후 api 테스트를 해보니 이상없이 동작한다.
@Getter
@NoArgsConstructor(force = true, access = AccessLevel.PROTECTED)
@RequiredArgsConstructor
public class CommentRequest {
private final String content;
}
롬복의 @builder는 기본생성자를 생성해주지 않기에 이런 상황이 발생했다. 다음부터는 조심해서 써야겠다.
여기를 보고 참고했다.
@Builder를 추가했더니 잭슨에서 에러가?
💣📌@RequestBody 에서 DTO 변환시 기본생성자를 필요로한다.일반적인 경우 기본생성자를 사용한다. (리플렉션 통해 생성되기 때문에 Private 가능)@JsonProperty 를 사용하는 프로퍼티 기반 객체는 필요
91ms.tistory.com