Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

리뷰 삭제 기능 추가 #114

Merged
merged 3 commits into from
Jan 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions src/docs/asciidoc/api-doc.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -425,6 +425,22 @@ include::{snippets}/review-controller-test/respond_200_when_succeed_to_delete_re
| `404 NOT FOUND` | `NOT_FOUND_REVIEW` | 해당하는 리뷰가 없는 경우
| `404 NOT FOUND` | `NOT_FOUND_REVIEW_LIKE` | 해당하는 리뷰 좋아요가 없는 경우
|===

=== 4-7. 리뷰 삭제
==== Path Parameters
include::{snippets}/review-controller-test/respond_200_when_succeed_to_delete_review/path-parameters.adoc[]
==== Sample Request
include::{snippets}/review-controller-test/respond_200_when_succeed_to_delete_review/http-request.adoc[]
==== Sample Response
include::{snippets}/review-controller-test/respond_200_when_succeed_to_delete_review/http-response.adoc[]
==== Error Response
|===
| HTTP Status | Error Code | Detail

| `403 FORBIDDEN` | `FORBIDDEN_REVIEW` | 해당 리뷰에 대한 삭제 권한이 없는 경우
| `404 NOT FOUND` | `NOT_FOUND_REVIEW` | 해당하는 리뷰가 없는 경우
|===

== 5. 이미지
=== 5-1. 이미지 업로드
==== Path Parameters
Expand Down
6 changes: 6 additions & 0 deletions src/main/java/com/cvsgo/controller/ReviewController.java
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,12 @@ public SuccessResponse<Void> updateReview(@LoginUser User user, @PathVariable Lo
return SuccessResponse.create();
}

@DeleteMapping("/reviews/{reviewId}")
public SuccessResponse<Void> deleteReview(@LoginUser User user, @PathVariable Long reviewId) {
reviewService.deleteReview(user, reviewId);
return SuccessResponse.create();
}

@PostMapping("/reviews/{reviewId}/likes")
@ResponseStatus(HttpStatus.CREATED)
public SuccessResponse<Void> createReviewLike(@LoginUser User user,
Expand Down
15 changes: 15 additions & 0 deletions src/main/java/com/cvsgo/service/ReviewService.java
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,21 @@ public void updateReview(User user, Long reviewId, UpdateReviewRequestDto reques
review.updateRating(request.getRating());
}

/**
* 리뷰를 삭제합니다.
*
* @param user 현재 로그인한 사용자
* @param reviewId 삭제하려는 리뷰 ID
*/
@Transactional
public void deleteReview(User user, Long reviewId) {
Review review = reviewRepository.findById(reviewId).orElseThrow(() -> NOT_FOUND_REVIEW);
if (!review.getUser().equals(user)) {
throw FORBIDDEN_REVIEW;
}
reviewRepository.delete(review);
}

/**
* 필터를 적용하여 리뷰를 조회합니다.
*
Expand Down
20 changes: 18 additions & 2 deletions src/test/java/com/cvsgo/controller/ReviewControllerTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ class ReviewControllerTest {

private static final String PRODUCT_REVIEW_API_PATH = "/api/products/{productId}/reviews";

private static final String UPDATE_REVIEW_API_PATH = "/api/reviews/{reviewId}";
private static final String REVIEW_API_PATH = "/api/reviews/{reviewId}";

private static final String SEARCH_REVIEW_API_PATH = "/api/reviews";

Expand Down Expand Up @@ -267,7 +267,7 @@ void respond_200_when_succeed_to_update_review() throws Exception {
UpdateReviewRequestDto requestDto = new UpdateReviewRequestDto(5, "맛있어요",
List.of("리뷰 이미지 URL 1", "리뷰 이미지 URL 2"));

mockMvc.perform(put(UPDATE_REVIEW_API_PATH, 1)
mockMvc.perform(put(REVIEW_API_PATH, 1)
.content(objectMapper.writeValueAsString(requestDto))
.contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isOk()).andDo(print())
Expand Down Expand Up @@ -450,6 +450,22 @@ void respond_500_when_delete_review_like_but_concurrency_issue_occurs() throws E
.andDo(print());
}

@Test
@DisplayName("리뷰 삭제에 성공하면 HTTP 200을 응답한다")
void respond_200_when_succeed_to_delete_review() throws Exception {
mockMvc.perform(delete(REVIEW_API_PATH, 1)
.contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andDo(print())
.andDo(document(documentIdentifier,
getDocumentRequest(),
getDocumentResponse(),
pathParameters(
parameterWithName("reviewId").description("리뷰 ID")
)
));
}

ReviewDto responseDto1 = ReviewDto.builder()
.productId(13L)
.productName("불닭볶음면큰컵")
Expand Down
30 changes: 30 additions & 0 deletions src/test/java/com/cvsgo/service/ReviewServiceTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -432,6 +432,36 @@ void succeed_to_read_user_review() {
assertThat(reviews.size()).isEqualTo(1);
}

@Test
@DisplayName("특정 리뷰를 정상적으로 삭제한다.")
void succeed_to_delete_review() {
given(reviewRepository.findById(any())).willReturn(Optional.of(review));

reviewService.deleteReview(user2, 1L);

then(reviewRepository).should(times(1)).findById(anyLong());
then(reviewRepository).should(times(1)).delete(any());
}

@Test
@DisplayName("리뷰 작성자가 아닌 사용자가 리뷰 삭제를 시도하면 ForbiddenException이 발생한다.")
void should_throw_ForbiddenException_when_delete_review_but_review_does_not_exist() {
given(reviewRepository.findById(any())).willReturn(Optional.of(review));

assertThrows(ForbiddenException.class,
() -> reviewService.deleteReview(user1, 1L));
}

@Test
@DisplayName("존재하지 않는 리뷰를 삭제하면 NotFoundException이 발생한다.")
void should_throw_NotFoundException_when_delete_review_but_review_does_not_exist() {
given(reviewRepository.findById(any())).willReturn(Optional.empty());

assertThrows(NotFoundException.class,
() -> reviewService.deleteReview(user1, 1000L));
}


User user1 = User.builder()
.id(1L)
.userId("[email protected]")
Expand Down