-
[내일배움캠프] 3월 2일 목요일 TIL 회고록카테고리 없음 2023. 3. 3. 00:48
오늘 배운 것 : 테스트 코드 작성
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