포스트 삭제, 포스트 리스트 조회 기능을 구현하자.
@Test
@DisplayName("포스트 삭제 성공")
@WithMockUser
void post_delete_SUCCESS() throws Exception {
String title = "테스트";
String body = "테스트입니다.";
when(postService.delete(any(),any()))
.thenReturn(new PostResponse("포스트 삭제 완료", 1l));
mockMvc.perform(delete("/api/v1/posts/1")
.with(csrf())
.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsBytes(new PostRequest(title, body))))
.andDo(print())
.andExpect(status().isOk());
}
@Test
@DisplayName("포스트 삭제 실패1_인증")
@WithAnonymousUser
void post_delete_FAILED_authentication() throws Exception {
String title = "테스트";
String body = "테스트입니다.";
when(postService.delete(any(),any()))
.thenThrow(new AppException(ErrorCode.INVALID_PERMISSION,ErrorCode.INVALID_PERMISSION.getMessage()));
mockMvc.perform(delete("/api/v1/posts/1")
.with(csrf())
.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsBytes(new PostRequest(title, body))))
.andDo(print())
.andExpect(status().isUnauthorized());
}
@Test
@DisplayName("포스트 삭제 실패2_작성자 불일치")
@WithMockUser
void post_delete_FAILED_different() throws Exception {
String title = "테스트";
String body = "테스트입니다.";
when(postService.delete(any(),any()))
.thenThrow(new AppException(ErrorCode.INVALID_PERMISSION,ErrorCode.INVALID_PERMISSION.getMessage()));
mockMvc.perform(delete("/api/v1/posts/1")
.with(csrf())
.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsBytes(new PostRequest(title, body))))
.andDo(print())
.andExpect(status().isUnauthorized());
}
@Test
@DisplayName("포스트 삭제 실패3_데이터베이스 에러")
@WithMockUser
void post_delete_FAILED_db() throws Exception {
String title = "테스트";
String body = "테스트입니다.";
when(postService.delete(any(),any()))
.thenThrow(new AppException(ErrorCode.DATABASE_ERROR,ErrorCode.DATABASE_ERROR.getMessage()));
mockMvc.perform(delete("/api/v1/posts/1")
.with(csrf())
.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsBytes(new PostRequest(title, body))))
.andDo(print())
.andExpect(status().isInternalServerError());
}
@Test
@DisplayName("포스트 삭제 성공")
void post_delete_SUCCESS() {
when(postRepository.findById(any()))
.thenReturn(Optional.of(post));
when(userRepository.findByUserName(any()))
.thenReturn(Optional.of(user));
assertDoesNotThrow(() -> postService.delete(user.getUserName(), post.getId()));
}
@Test
@DisplayName("포스트 삭제 실패1_포스트가 존재하지 않는 경우")
void post_delete_FAILED_not_found_post() {
when(postRepository.findById(any()))
.thenReturn(Optional.empty());
when(userRepository.findByUserName(any()))
.thenReturn(Optional.of(user));
AppException exception = assertThrows(AppException.class, () -> postService.delete(user.getUserName(), post.getId()));
assertEquals(ErrorCode.POST_NOT_FOUND, exception.getErrorCode());
}
@Test
@DisplayName("포스트 수정 실패2_포스트 작성자와 유저가 다른 경우")
void post_delete_FAILED_different() {
when(postRepository.findById(any()))
.thenReturn(Optional.of(post));
when(userRepository.findByUserName(any()))
.thenReturn(Optional.of(user2));
AppException exception = assertThrows(AppException.class, () -> postService.delete(user2.getUserName(), post.getId()));
assertEquals(ErrorCode.INVALID_PERMISSION, exception.getErrorCode());
}
@Test
@DisplayName("포스트 수정 실패3_유저가 존재하지 않는 경우")
void post_delete_FAILED_not_found_userName() {
when(postRepository.findById(any()))
.thenReturn(Optional.of(post));
when(userRepository.findByUserName(any()))
.thenReturn(Optional.empty());
AppException exception = assertThrows(AppException.class, () -> postService.delete(user.getUserName(), post.getId()));
assertEquals(ErrorCode.INVALID_PERMISSION, exception.getErrorCode());
}
@DeleteMapping("/{id}")
public ResponseEntity<Response> deletePost(@PathVariable Long id, Authentication authentication) {
String userName = null;
try {
userName = authentication.getName();
} catch (Exception e) {
throw new AppException(ErrorCode.INVALID_TOKEN, ErrorCode.INVALID_TOKEN.getMessage());
}
PostResponse postResponse = postService.delete(userName, id);
return ResponseEntity.ok().body(Response.of("SUCCESS", postResponse));
}
public PostResponse delete(String userName, Long id) {
//포스트 체크
Post deletePost = postRepository.findById(id).orElseThrow(() -> {
throw new AppException(ErrorCode.POST_NOT_FOUND, ErrorCode.POST_NOT_FOUND.getMessage());
});
//유저 체크
User user = userRepository.findByUserName(userName).orElseThrow(() -> {
throw new AppException(ErrorCode.INVALID_PERMISSION, ErrorCode.INVALID_PERMISSION.getMessage());
});
//포스트 유저와 유처 비교
if (!deletePost.getUser().getUserName().equals(user.getUserName())) {
throw new AppException(ErrorCode.INVALID_PERMISSION, ErrorCode.INVALID_PERMISSION.getMessage());
}
//포스트 삭제 후 DTO 리턴
postRepository.deleteById(deletePost.getId());
PostResponse postResponse = PostResponse.of("포스트 삭제 완료", deletePost.getId());
return postResponse;
}
@Test
@DisplayName("pageable 파라미터 검증")
@WithMockUser
void post_get_posts_SUCCESS() throws Exception {
mockMvc.perform(get("/api/v1/posts")
.with(csrf())
.param("page", "0")
.param("size", "3")
.param("sort", "createdAt,desc"))
.andExpect(status().isOk());
ArgumentCaptor<Pageable> pageableCaptor = ArgumentCaptor.forClass(Pageable.class);
verify(postService).getPosts(pageableCaptor.capture());
PageRequest pageRequest = (PageRequest) pageableCaptor.getValue();
assertEquals(0, pageRequest.getPageNumber());
assertEquals(3, pageRequest.getPageSize());
assertEquals(Sort.by("createdAt","desc"), pageRequest.withSort(Sort.by("createdAt","desc")).getSort());
}
@GetMapping
public ResponseEntity<Response<Page<PostGetResponse>>> getPosts(@PageableDefault(size = 20, sort = "createdAt",direction = Sort.Direction.DESC) Pageable pageable){
Page<PostGetResponse> postGetResponses = postService.getPosts(pageable);
return ResponseEntity.ok().body(Response.of("SUCCESS",postGetResponses));
}
public Page<PostGetResponse> getPosts(Pageable pageable) {
Page<Post> posts = postRepository.findAll(pageable);
Page<PostGetResponse> postGetResponses = PostGetResponse.toResponses(posts);
return postGetResponses;
}
public static Page<PostGetResponse> toResponses(Page<Post> posts) {
Page<PostGetResponse> postGetResponses = posts.map(m -> PostGetResponse.builder()
.id(m.getId())
.title(m.getTitle())
.body(m.getBody())
.userName(m.getUser().getUserName())
.createdAt(m.getCreatedAt())
.lastModifiedAt(m.getModifiedAt())
.build());
return postGetResponses;
}