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

[BE] fix: ReviewDeleteEventListenerTest 통과하도록 수정 #778

Merged
merged 9 commits into from
Oct 18, 2023
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public ReviewDeleteEventListener(final ImageUploader imageUploader) {
@TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)
public void deleteReviewImageInS3(final ReviewDeleteEvent event) {
final String image = event.getImage();
if (StringUtils.isBlank(image)) {
if (!StringUtils.isBlank(image)) {
imageUploader.delete(image);
}
hanueleee marked this conversation as resolved.
Show resolved Hide resolved
}
Expand Down
20 changes: 10 additions & 10 deletions backend/src/test/java/com/funeat/common/EventTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,8 @@
import com.funeat.product.persistence.ProductRepository;
import com.funeat.review.application.ReviewService;
import com.funeat.review.persistence.ReviewRepository;
import com.funeat.tag.domain.Tag;
import com.funeat.tag.persistence.TagRepository;
import java.util.List;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.DisplayNameGeneration;
import org.junit.jupiter.api.DisplayNameGenerator.ReplaceUnderscores;
import org.junit.jupiter.api.extension.ExtendWith;
Expand All @@ -22,13 +21,17 @@

@SpringBootTest
@RecordApplicationEvents
@ExtendWith(MockitoExtension.class)
@SuppressWarnings("NonAsciiCharacters")
@DisplayNameGeneration(ReplaceUnderscores.class)
@ExtendWith({MockitoExtension.class, DataClearExtension.class})
public class EventTest {

@Autowired
protected ApplicationEvents events;

@Autowired
protected ReviewService reviewService;

@Autowired
protected ProductRepository productRepository;

Expand All @@ -44,8 +47,10 @@ public class EventTest {
@Autowired
protected ReviewRepository reviewRepository;

@Autowired
protected ReviewService reviewService;
@AfterEach
void tearDown() {
events.clear();
}

protected Long 단일_상품_저장(final Product product) {
return productRepository.save(product).getId();
Expand All @@ -55,11 +60,6 @@ public class EventTest {
return categoryRepository.save(category).getId();
}

protected void 복수_태그_저장(final Tag... tagsToSave) {
final var tags = List.of(tagsToSave);
tagRepository.saveAll(tags);
}

protected Long 단일_멤버_저장(final Member member) {
return memberRepository.save(member).getId();
}
Expand Down
4 changes: 4 additions & 0 deletions backend/src/test/java/com/funeat/fixture/ReviewFixture.java
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,10 @@ public class ReviewFixture {
return new Review(member, product, "test5", 5L, "test", false, count);
}

public static Review 리뷰_이미지없음_평점1점_재구매X_생성(final Member member, final Product product, final Long count) {
return new Review(member, product, "", 1L, "test", false, count);
}

public static ReviewCreateRequest 리뷰추가요청_생성(final Long rating, final List<Long> tagIds, final String content,
final Boolean rebuy) {
return new ReviewCreateRequest(rating, tagIds, content, rebuy);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
package com.funeat.review.application;

import static com.funeat.fixture.CategoryFixture.카테고리_즉석조리_생성;
import static com.funeat.fixture.ImageFixture.이미지_생성;
import static com.funeat.fixture.MemberFixture.멤버_멤버1_생성;
import static com.funeat.fixture.MemberFixture.멤버_멤버2_생성;
import static com.funeat.fixture.ProductFixture.상품_삼각김밥_가격1000원_평점2점_생성;
import static com.funeat.fixture.ReviewFixture.리뷰추가요청_재구매O_생성;
import static com.funeat.fixture.TagFixture.태그_맛있어요_TASTE_생성;
import static com.funeat.fixture.TagFixture.태그_아침식사_ETC_생성;
import static com.funeat.fixture.ReviewFixture.리뷰_이미지test1_평점1점_재구매O_생성;
import static com.funeat.fixture.ReviewFixture.리뷰_이미지test2_평점2점_재구매O_생성;
import static com.funeat.fixture.ReviewFixture.리뷰_이미지test3_평점3점_재구매O_생성;
import static com.funeat.fixture.ReviewFixture.리뷰_이미지test4_평점4점_재구매O_생성;
import static com.funeat.fixture.ReviewFixture.리뷰_이미지없음_평점1점_재구매X_생성;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doThrow;
Expand All @@ -18,14 +19,11 @@
import com.funeat.common.ImageUploader;
import com.funeat.common.exception.CommonException.S3DeleteFailException;
import com.funeat.exception.CommonErrorCode;
import com.funeat.tag.domain.Tag;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.mock.mockito.MockBean;

@SuppressWarnings("NonAsciiCharacters")
class ReviewDeleteEventListenerTest extends EventTest {

@MockBean
Expand All @@ -37,30 +35,19 @@ class 리뷰_삭제_이벤트_발행 {
@Test
void 리뷰_작성자가_리뷰_삭제_시도시_리뷰_삭제_이벤트가_발행된다() {
// given
final var member = 멤버_멤버1_생성();
final var memberId = 단일_멤버_저장(member);
final var author = 멤버_멤버1_생성();
final var authorId = 단일_멤버_저장(author);

final var category = 카테고리_즉석조리_생성();
단일_카테고리_저장(category);

final var product = 상품_삼각김밥_가격1000원_평점2점_생성(category);
final var productId = 단일_상품_저장(product);

final var tag1 = 태그_맛있어요_TASTE_생성();
final var tag2 = 태그_아침식사_ETC_생성();
복수_태그_저장(tag1, tag2);

final var tagIds = 태그_아이디_변환(tag1, tag2);
final var image = 이미지_생성();
단일_상품_저장(product);

final var request = 리뷰추가요청_재구매O_생성(4L, tagIds);
reviewService.create(productId, memberId, image, request);

final var review = reviewRepository.findAll().get(0);
final var reviewId = review.getId();
final var review = reviewRepository.save(리뷰_이미지test1_평점1점_재구매O_생성(author, product, 0L));

// when
reviewService.deleteReview(reviewId, memberId);
reviewService.deleteReview(review.getId(), authorId);

// then
final var count = events.stream(ReviewDeleteEvent.class).count();
Expand All @@ -70,33 +57,23 @@ class 리뷰_삭제_이벤트_발행 {
@Test
void 리뷰_작성자가_아닌_사람이_리뷰_삭제_시도시_리뷰_삭제_이벤트가_발행되지_않는다() {
// given
final var author = 멤버_멤버2_생성();
final var author = 멤버_멤버1_생성();
final var authorId = 단일_멤버_저장(author);
final var member = 멤버_멤버1_생성();

final var member = 멤버_멤버2_생성();
final var memberId = 단일_멤버_저장(member);

final var category = 카테고리_즉석조리_생성();
단일_카테고리_저장(category);

final var product = 상품_삼각김밥_가격1000원_평점2점_생성(category);
final var productId = 단일_상품_저장(product);

final var tag1 = 태그_맛있어요_TASTE_생성();
final var tag2 = 태그_아침식사_ETC_생성();
복수_태그_저장(tag1, tag2);
단일_상품_저장(product);

final var tagIds = 태그_아이디_변환(tag1, tag2);
final var image = 이미지_생성();

final var request = 리뷰추가요청_재구매O_생성(4L, tagIds);
reviewService.create(productId, authorId, image, request);

final var review = reviewRepository.findAll().get(0);
final var reviewId = review.getId();
final var review = reviewRepository.save(리뷰_이미지test2_평점2점_재구매O_생성(author, product, 0L));

// when
try {
reviewService.deleteReview(reviewId, memberId);
reviewService.deleteReview(review.getId(), memberId);
} catch (Exception ignored) {
}

Expand All @@ -112,106 +89,68 @@ class 이미지_삭제_로직_작동 {
@Test
void 리뷰_삭제가_정상적으로_커밋되고_이미지가_존재하면_이미지_삭제_로직이_작동한다() {
// given
final var member = 멤버_멤버1_생성();
final var memberId = 단일_멤버_저장(member);
final var author = 멤버_멤버1_생성();
final var authorId = 단일_멤버_저장(author);

final var category = 카테고리_즉석조리_생성();
단일_카테고리_저장(category);

final var product = 상품_삼각김밥_가격1000원_평점2점_생성(category);
final var productId = 단일_상품_저장(product);

final var tag1 = 태그_맛있어요_TASTE_생성();
final var tag2 = 태그_아침식사_ETC_생성();
복수_태그_저장(tag1, tag2);

final var tagIds = 태그_아이디_변환(tag1, tag2);
final var image = 이미지_생성();
단일_상품_저장(product);

final var request = 리뷰추가요청_재구매O_생성(4L, tagIds);
reviewService.create(productId, memberId, image, request);

final var review = reviewRepository.findAll().get(0);
final var reviewId = review.getId();
final var review = reviewRepository.save(리뷰_이미지test3_평점3점_재구매O_생성(author, product, 0L));

// when
reviewService.deleteReview(reviewId, memberId);
reviewService.deleteReview(review.getId(), authorId);

// then
verify(uploader, timeout(100).times(1)).delete(any());
verify(uploader, timeout(1000).times(1)).delete(any());
}

@Test
void 리뷰_삭제가_정상적으로_커밋되었지만_이미지가_존재하지_않으면_이미지_삭제_로직이_작동하지않는다() {
// given
final var member = 멤버_멤버1_생성();
final var memberId = 단일_멤버_저장(member);
final var author = 멤버_멤버1_생성();
final var authorId = 단일_멤버_저장(author);

final var category = 카테고리_즉석조리_생성();
단일_카테고리_저장(category);

final var product = 상품_삼각김밥_가격1000원_평점2점_생성(category);
final var productId = 단일_상품_저장(product);

final var tag1 = 태그_맛있어요_TASTE_생성();
final var tag2 = 태그_아침식사_ETC_생성();
복수_태그_저장(tag1, tag2);
단일_상품_저장(product);

final var tagIds = 태그_아이디_변환(tag1, tag2);

final var request = 리뷰추가요청_재구매O_생성(4L, tagIds);
reviewService.create(productId, memberId, null, request);

final var review = reviewRepository.findAll().get(0);
final var reviewId = review.getId();
final var review = reviewRepository.save(리뷰_이미지없음_평점1점_재구매X_생성(author, product, 0L));

// when
reviewService.deleteReview(reviewId, memberId);
reviewService.deleteReview(review.getId(), authorId);

// then
verify(uploader, timeout(100).times(0)).delete(any());
verify(uploader, timeout(1000).times(0)).delete(any());
}

@Test
void 이미지_삭제_로직이_실패해도_메인로직까지_롤백되어서는_안된다() {
// given
final var member = 멤버_멤버1_생성();
final var memberId = 단일_멤버_저장(member);
final var author = 멤버_멤버1_생성();
final var authorId = 단일_멤버_저장(author);

final var category = 카테고리_즉석조리_생성();
단일_카테고리_저장(category);

final var product = 상품_삼각김밥_가격1000원_평점2점_생성(category);
final var productId = 단일_상품_저장(product);

final var tag1 = 태그_맛있어요_TASTE_생성();
final var tag2 = 태그_아침식사_ETC_생성();
복수_태그_저장(tag1, tag2);

final var tagIds = 태그_아이디_변환(tag1, tag2);
final var image = 이미지_생성();
단일_상품_저장(product);

final var request = 리뷰추가요청_재구매O_생성(4L, tagIds);
reviewService.create(productId, memberId, image, request);

final var review = reviewRepository.findAll().get(0);
final var reviewId = review.getId();
final var review = reviewRepository.save(리뷰_이미지test4_평점4점_재구매O_생성(author, product, 0L));

doThrow(new S3DeleteFailException(CommonErrorCode.UNKNOWN_SERVER_ERROR_CODE))
.when(uploader)
.delete(any());

// when
reviewService.deleteReview(reviewId, memberId);
reviewService.deleteReview(review.getId(), authorId);

// then
assertThat(reviewRepository.findById(reviewId)).isEmpty();
assertThat(reviewRepository.findById(review.getId())).isEmpty();
}
}

private List<Long> 태그_아이디_변환(final Tag... tags) {
return Stream.of(tags)
.map(Tag::getId)
.collect(Collectors.toList());
}
}