✨개요
🏃 목표
📢 댓글을 수정하는 기능을 구현하자.
📜 접근방법
✅ TO-DO
🔧 구현
댓글 수정 컨트롤러 테스트 구현
댓글 수정 성공
<@Test
@DisplayName("댓글 수정 성공")
@WithMockUser
void comment_modify_SUCCESS() throws Exception {
when(commentService.modify("홍길동", 1L, 1L, "테스트입니다."))
.thenReturn(commentModifyResponse);
mockMvc.perform(put("/api/v1/posts/1/comments/1")
.with(csrf())
.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsBytes(new CommentRequest("테스트입니다."))))
.andDo(print())
.andExpect(status().isOk());
}
댓글 수정 실패
@Test
@DisplayName("댓글 수정 실패1_로그인을 하지 않은 경우")
@WithAnonymousUser
void comment_modify_FAILD_login() throws Exception {
when(commentService.modify("홍길동", 1L, 1L, "테스트입니다."))
.thenThrow(new AppException(ErrorCode.USERNAME_NOT_FOUND, ErrorCode.USERNAME_NOT_FOUND.getMessage()));
mockMvc.perform(put("/api/v1/posts/1/comments/1")
.with(csrf())
.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsBytes(new CommentRequest("테스트입니다."))))
.andDo(print())
.andExpect(status().isUnauthorized());
}
@Test
@DisplayName("댓글 작성 실패2_작성자 불일치인 경우")
@WithMockUser
void comment_modify_FAIL_different() throws Exception {
when(commentService.modify(any(), any(), any(), any()))
.thenThrow(new AppException(ErrorCode.INVALID_PERMISSION, ErrorCode.INVALID_PERMISSION.getMessage()));
mockMvc.perform(put("/api/v1/posts/1/comments/1")
.with(csrf())
.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsBytes(new CommentRequest("테스트입니다."))))
.andDo(print())
.andExpect(status().isUnauthorized());
}
@Test
@DisplayName("댓글 작성 실패3_DB 에러인 경우")
@WithMockUser
void comment_modify_FAIL_db() throws Exception {
when(commentService.modify(any(), any(), any(), any()))
.thenThrow(new AppException(ErrorCode.DATABASE_ERROR, ErrorCode.DATABASE_ERROR.getMessage()));
mockMvc.perform(put("/api/v1/posts/1/comments/1")
.with(csrf())
.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsBytes(new CommentRequest("테스트입니다."))))
.andDo(print())
.andExpect(status().isInternalServerError());
}
댓글 수정 서비스 테스트 구현
댓글 수정 성공
@Test
@DisplayName("댓글 수정 성공")
void comment_modify_SUCCESS() {
when(userRepository.findByUserName(any()))
.thenReturn(Optional.of(user));
when(postRepository.findById(any()))
.thenReturn(Optional.of(post));
when(commentRepository.findById(any()))
.thenReturn(Optional.of(comment));
when(commentRepository.saveAndFlush(any()))
.thenReturn(comment);
assertDoesNotThrow(() -> commentService.modify(user.getUserName(), post.getId(), comment.getId(), comment.getComment()));
}
댓글 수정 실패
@Test
@DisplayName("댓글 수정 실패2_포스트가 없는 경우")
void comment_modify_FALID_post() {
when(userRepository.findByUserName(any()))
.thenReturn(Optional.of(user));
when(postRepository.findById(any()))
.thenReturn(Optional.empty());
when(commentRepository.saveAndFlush(any()))
.thenReturn(comment);
AppException exception = assertThrows(AppException.class, () -> commentService.modify(user.getUserName(), post.getId(), comment.getId(), comment.getComment()));
assertEquals(ErrorCode.POST_NOT_FOUND, exception.getErrorCode());
}
@Test
@DisplayName("댓글 수정 실패3_작성자 불일치인 경우")
void comment_modify_FALID_different() {
when(userRepository.findByUserName(any()))
.thenReturn(Optional.of(user2));
when(postRepository.findById(any()))
.thenReturn(Optional.of(post));
when(commentRepository.findById(any()))
.thenReturn(Optional.of(comment));
when(commentRepository.saveAndFlush(any()))
.thenReturn(comment);
AppException exception = assertThrows(AppException.class, () -> commentService.modify(user2.getUserName(), post.getId(), comment.getId(), comment.getComment()));
assertEquals(ErrorCode.INVALID_PERMISSION, exception.getErrorCode());
}
@Test
@DisplayName("댓글 수정 실패1_유저가 존재하지 않는 경우")
void comment_modify_FALID_user() {
when(userRepository.findByUserName(any()))
.thenReturn(Optional.empty());
when(postRepository.findById(any()))
.thenReturn(Optional.of(post));
when(commentRepository.saveAndFlush(any()))
.thenReturn(comment);
AppException exception = assertThrows(AppException.class, () -> commentService.modify(user.getUserName(), post.getId(), comment.getId(), comment.getComment()));
assertEquals(ErrorCode.USERNAME_NOT_FOUND, exception.getErrorCode());
}
댓글 수정 컨트롤러 구현
@PutMapping("/{id}")
public ResponseEntity<Response> modify(Authentication authentication, @PathVariable Long postId, @PathVariable Long id, @RequestBody CommentRequest commentRequest){
String userName = authentication.getName();
CommentModifyResponse commentModifyResponse = commentService.modify(userName,postId,id,commentRequest.getComment());
return ResponseEntity.ok().body(Response.of("SUCCESS", commentModifyResponse));
}
@AllArgsConstructor
@NoArgsConstructor
@Builder
@Getter
@Setter
public class CommentModifyResponse {
private Long id;
private String comment;
private String userName;
private Long postId;
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd' 'HH:mm:ss", timezone = "Asia/Seoul")
private LocalDateTime createdAt;
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd' 'HH:mm:ss", timezone = "Asia/Seoul")
private LocalDateTime lastModifiedAt;
public static CommentModifyResponse of(Comment comment) {
return CommentModifyResponse.builder()
.id(comment.getId())
.comment(comment.getComment())
.userName(comment.getUser().getUserName())
.postId(comment.getPost().getId())
.createdAt(comment.getCreatedAt())
.lastModifiedAt(comment.getLastModifiedAt())
.build();
}
}
댓글 수정 서비스 구현
public CommentModifyResponse modify(String userName, Long postId, Long id, String comment) {
User findUser = AppUtil.findUser(userRepository, userName);
Post findPost = AppUtil.findPost(postRepository, postId);
Comment findComment = AppUtil.findComment(commentRepository, id);
AppUtil.compareUser(findComment.getUser().getUserName(), findUser.getUserName());
findComment.modify(comment);
commentRepository.saveAndFlush(findComment);
return CommentModifyResponse.of(findComment);
}
AppUtil 메서드 추가
public static Comment findComment(CommentRepository commentRepository, Long id) {
return commentRepository.findById(id).orElseThrow(() -> {
throw new AppException(ErrorCode.COMMENT_NOT_FOUND, ErrorCode.COMMENT_NOT_FOUND.getMessage());
});
}
public void modify(String comment) {
this.comment = comment;
}
🌉회고
📖 회고
- 구현하는 과정은 익숙해져 갔다.
- 하지만 반복되는 코드 내용이 점점 많아지면서 AOP에 대해 공부할 필요성을 느끼게 되었다.