From f54a056c861e3390762891a6efc621a3a593f0b2 Mon Sep 17 00:00:00 2001 From: wugawuga Date: Sun, 13 Aug 2023 16:06:32 +0900 Subject: [PATCH 1/4] =?UTF-8?q?feat:=20=EC=82=AC=EC=9A=A9=EC=9E=90=20?= =?UTF-8?q?=EB=A7=88=EC=9D=B4=ED=8E=98=EC=9D=B4=EC=A7=80=20=EB=A6=AC?= =?UTF-8?q?=EB=B7=B0=20=EC=A1=B0=ED=9A=8C=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/funeat/common/WebConfig.java | 2 +- .../funeat/member/dto/MemberReviewDto.java | 58 ++++++++ .../member/dto/MemberReviewsResponse.java | 28 ++++ .../presentation/MemberApiController.java | 20 ++- .../member/presentation/MemberController.java | 12 ++ .../review/application/ReviewService.java | 16 +++ .../review/persistence/ReviewRepository.java | 8 +- .../presentation/dto/RankingReviewDto.java | 8 +- .../member/MemberAcceptanceTest.java | 131 ++++++++++++++++++ .../funeat/acceptance/member/MemberSteps.java | 12 ++ .../review/application/ReviewServiceTest.java | 66 +++++++++ 11 files changed, 348 insertions(+), 13 deletions(-) create mode 100644 backend/src/main/java/com/funeat/member/dto/MemberReviewDto.java create mode 100644 backend/src/main/java/com/funeat/member/dto/MemberReviewsResponse.java diff --git a/backend/src/main/java/com/funeat/common/WebConfig.java b/backend/src/main/java/com/funeat/common/WebConfig.java index 1d89f8aa7..4691efbe4 100644 --- a/backend/src/main/java/com/funeat/common/WebConfig.java +++ b/backend/src/main/java/com/funeat/common/WebConfig.java @@ -32,7 +32,7 @@ public WebConfig(final CustomPageableHandlerMethodArgumentResolver customPageabl public void addInterceptors(final InterceptorRegistry registry) { registry.addInterceptor(authHandlerInterceptor) .addPathPatterns("/api/products/**/reviews/**") - .addPathPatterns("/api/members"); + .addPathPatterns("/api/members/**"); registry.addInterceptor(recipeHandlerInterceptor) .addPathPatterns("/api/recipes"); } diff --git a/backend/src/main/java/com/funeat/member/dto/MemberReviewDto.java b/backend/src/main/java/com/funeat/member/dto/MemberReviewDto.java new file mode 100644 index 000000000..c3b441ee1 --- /dev/null +++ b/backend/src/main/java/com/funeat/member/dto/MemberReviewDto.java @@ -0,0 +1,58 @@ +package com.funeat.member.dto; + +import com.funeat.review.domain.Review; + +public class MemberReviewDto { + + private final Long reviewId; + private final Long productId; + private final String productName; + private final String content; + private final Long rating; + private final Long favoriteCount; + + private MemberReviewDto(final Long reviewId, final Long productId, final String productName, final String content, + final Long rating, final Long favoriteCount) { + this.reviewId = reviewId; + this.productId = productId; + this.productName = productName; + this.content = content; + this.rating = rating; + this.favoriteCount = favoriteCount; + } + + public static MemberReviewDto toDto(final Review review) { + return new MemberReviewDto( + review.getId(), + review.getProduct().getId(), + review.getProduct().getName(), + review.getContent(), + review.getRating(), + review.getFavoriteCount() + ); + } + + public Long getReviewId() { + return reviewId; + } + + public Long getProductId() { + return productId; + } + + public String getProductName() { + return productName; + } + + public String getContent() { + return content; + } + + public Long getRating() { + return rating; + } + + public Long getFavoriteCount() { + return favoriteCount; + } +} diff --git a/backend/src/main/java/com/funeat/member/dto/MemberReviewsResponse.java b/backend/src/main/java/com/funeat/member/dto/MemberReviewsResponse.java new file mode 100644 index 000000000..300b460a8 --- /dev/null +++ b/backend/src/main/java/com/funeat/member/dto/MemberReviewsResponse.java @@ -0,0 +1,28 @@ +package com.funeat.member.dto; + +import com.funeat.review.presentation.dto.SortingReviewsPageDto; +import java.util.List; + +public class MemberReviewsResponse { + + private final SortingReviewsPageDto page; + private final List reviews; + + private MemberReviewsResponse(final SortingReviewsPageDto page, final List reviews) { + this.page = page; + this.reviews = reviews; + } + + public static MemberReviewsResponse toResponse(final SortingReviewsPageDto page, + final List reviews) { + return new MemberReviewsResponse(page, reviews); + } + + public SortingReviewsPageDto getPage() { + return page; + } + + public List getReviews() { + return reviews; + } +} diff --git a/backend/src/main/java/com/funeat/member/presentation/MemberApiController.java b/backend/src/main/java/com/funeat/member/presentation/MemberApiController.java index a01ea5b2a..f49fe8003 100644 --- a/backend/src/main/java/com/funeat/member/presentation/MemberApiController.java +++ b/backend/src/main/java/com/funeat/member/presentation/MemberApiController.java @@ -5,23 +5,30 @@ import com.funeat.member.application.MemberService; import com.funeat.member.dto.MemberProfileResponse; import com.funeat.member.dto.MemberRequest; +import com.funeat.member.dto.MemberReviewsResponse; +import com.funeat.review.application.ReviewService; import javax.validation.Valid; +import org.springframework.data.domain.Pageable; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController +@RequestMapping("/api/members") public class MemberApiController implements MemberController { private final MemberService memberService; + private final ReviewService reviewService; - public MemberApiController(final MemberService memberService) { + public MemberApiController(final MemberService memberService, final ReviewService reviewService) { this.memberService = memberService; + this.reviewService = reviewService; } - @GetMapping("/api/members") + @GetMapping public ResponseEntity getMemberProfile( @AuthenticationPrincipal final LoginInfo loginInfo) { final Long memberId = loginInfo.getId(); @@ -31,7 +38,7 @@ public ResponseEntity getMemberProfile( return ResponseEntity.ok(response); } - @PutMapping("/api/members") + @PutMapping public ResponseEntity putMemberProfile(@AuthenticationPrincipal final LoginInfo loginInfo, @RequestBody @Valid final MemberRequest request) { final Long memberId = loginInfo.getId(); @@ -40,4 +47,11 @@ public ResponseEntity putMemberProfile(@AuthenticationPrincipal final Logi return ResponseEntity.ok().build(); } + + @GetMapping("/reviews") + public ResponseEntity getMemberReview(final LoginInfo loginInfo, final Pageable pageable) { + final MemberReviewsResponse response = reviewService.findReviewByMember(loginInfo.getId(), pageable); + + return ResponseEntity.ok().body(response); + } } diff --git a/backend/src/main/java/com/funeat/member/presentation/MemberController.java b/backend/src/main/java/com/funeat/member/presentation/MemberController.java index dee16f3b2..a10a034e5 100644 --- a/backend/src/main/java/com/funeat/member/presentation/MemberController.java +++ b/backend/src/main/java/com/funeat/member/presentation/MemberController.java @@ -4,9 +4,12 @@ import com.funeat.auth.util.AuthenticationPrincipal; import com.funeat.member.dto.MemberProfileResponse; import com.funeat.member.dto.MemberRequest; +import com.funeat.member.dto.MemberReviewsResponse; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.data.domain.Pageable; +import org.springframework.data.web.PageableDefault; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PutMapping; @@ -31,4 +34,13 @@ public interface MemberController { @PutMapping ResponseEntity putMemberProfile(@AuthenticationPrincipal LoginInfo loginInfo, @RequestBody MemberRequest request); + + @Operation(summary = "사용자 리뷰 조회", description = "사용자가 작성한 리뷰를 조회한다.") + @ApiResponse( + responseCode = "200", + description = "사용자 리뷰 조회 성공." + ) + @GetMapping + ResponseEntity getMemberReview(@AuthenticationPrincipal LoginInfo loginInfo, + @PageableDefault Pageable pageable); } diff --git a/backend/src/main/java/com/funeat/review/application/ReviewService.java b/backend/src/main/java/com/funeat/review/application/ReviewService.java index 6a186135c..2a88b1745 100644 --- a/backend/src/main/java/com/funeat/review/application/ReviewService.java +++ b/backend/src/main/java/com/funeat/review/application/ReviewService.java @@ -7,6 +7,8 @@ import com.funeat.common.ImageService; import com.funeat.member.domain.Member; import com.funeat.member.domain.favorite.ReviewFavorite; +import com.funeat.member.dto.MemberReviewDto; +import com.funeat.member.dto.MemberReviewsResponse; import com.funeat.member.exception.MemberException.MemberNotFoundException; import com.funeat.member.persistence.MemberRepository; import com.funeat.member.persistence.ReviewFavoriteRepository; @@ -139,4 +141,18 @@ public RankingReviewsResponse getTopReviews() { return RankingReviewsResponse.toResponse(dtos); } + + public MemberReviewsResponse findReviewByMember(final Long memberId, final Pageable pageable) { + final Member findMember = memberRepository.findById(memberId) + .orElseThrow(() -> new MemberNotFoundException(MEMBER_NOT_FOUND, memberId)); + + final Page sortedReviewPages = reviewRepository.findReviewsByMember(findMember, pageable); + final SortingReviewsPageDto pageDto = SortingReviewsPageDto.toDto(sortedReviewPages); + + final List dtos = sortedReviewPages.stream() + .map(MemberReviewDto::toDto) + .collect(Collectors.toList()); + + return MemberReviewsResponse.toResponse(pageDto, dtos); + } } diff --git a/backend/src/main/java/com/funeat/review/persistence/ReviewRepository.java b/backend/src/main/java/com/funeat/review/persistence/ReviewRepository.java index 209f3174c..573e52198 100644 --- a/backend/src/main/java/com/funeat/review/persistence/ReviewRepository.java +++ b/backend/src/main/java/com/funeat/review/persistence/ReviewRepository.java @@ -1,18 +1,20 @@ package com.funeat.review.persistence; +import com.funeat.member.domain.Member; import com.funeat.product.domain.Product; import com.funeat.review.domain.Review; +import java.util.List; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; -import java.util.List; - public interface ReviewRepository extends JpaRepository { Page findReviewsByProduct(final Pageable pageable, final Product product); List findTop3ByOrderByFavoriteCountDesc(); - + Long countByProduct(final Product product); + + Page findReviewsByMember(final Member findMember, final Pageable pageable); } diff --git a/backend/src/main/java/com/funeat/review/presentation/dto/RankingReviewDto.java b/backend/src/main/java/com/funeat/review/presentation/dto/RankingReviewDto.java index fcbaaed58..14057f8df 100644 --- a/backend/src/main/java/com/funeat/review/presentation/dto/RankingReviewDto.java +++ b/backend/src/main/java/com/funeat/review/presentation/dto/RankingReviewDto.java @@ -11,12 +11,8 @@ public class RankingReviewDto { private final Long rating; private final Long favoriteCount; - public RankingReviewDto(final Long reviewId, - final Long productId, - final String productName, - final String content, - final Long rating, - final Long favoriteCount) { + private RankingReviewDto(final Long reviewId, final Long productId, final String productName, final String content, + final Long rating, final Long favoriteCount) { this.reviewId = reviewId; this.productId = productId; this.productName = productName; diff --git a/backend/src/test/java/com/funeat/acceptance/member/MemberAcceptanceTest.java b/backend/src/test/java/com/funeat/acceptance/member/MemberAcceptanceTest.java index afe78f147..684d1417b 100644 --- a/backend/src/test/java/com/funeat/acceptance/member/MemberAcceptanceTest.java +++ b/backend/src/test/java/com/funeat/acceptance/member/MemberAcceptanceTest.java @@ -5,19 +5,36 @@ import static com.funeat.acceptance.common.CommonSteps.인증되지_않음; import static com.funeat.acceptance.common.CommonSteps.잘못된_요청; import static com.funeat.acceptance.common.CommonSteps.정상_처리; +import static com.funeat.acceptance.member.MemberSteps.사용자_리뷰_조회_요청; import static com.funeat.acceptance.member.MemberSteps.사용자_정보_수정_요청; import static com.funeat.acceptance.member.MemberSteps.사용자_정보_조회_요청; import static com.funeat.auth.exception.AuthErrorCode.LOGIN_MEMBER_NOT_FOUND; import static com.funeat.exception.CommonErrorCode.REQUEST_VALID_ERROR_CODE; +import static com.funeat.fixture.CategoryFixture.카테고리_즉석조리_생성; import static com.funeat.fixture.MemberFixture.멤버_멤버1_생성; +import static com.funeat.fixture.MemberFixture.멤버_멤버2_생성; +import static com.funeat.fixture.ProductFixture.상품_삼각김밥_가격1000원_평점5점_생성; +import static com.funeat.fixture.ProductFixture.상품_삼각김밥_가격2000원_평점1점_생성; +import static com.funeat.fixture.ProductFixture.상품_삼각김밥_가격2000원_평점3점_생성; +import static com.funeat.fixture.ReviewFixture.리뷰_이미지test1_평점1점_재구매X_생성; +import static com.funeat.fixture.ReviewFixture.리뷰_이미지test2_평점2점_재구매X_생성; +import static com.funeat.fixture.ReviewFixture.리뷰_이미지test3_평점3점_재구매O_생성; +import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.SoftAssertions.assertSoftly; import com.funeat.acceptance.common.AcceptanceTest; import com.funeat.member.domain.Member; import com.funeat.member.dto.MemberProfileResponse; import com.funeat.member.dto.MemberRequest; +import com.funeat.member.dto.MemberReviewDto; +import com.funeat.product.dto.ProductsInCategoryPageDto; +import com.funeat.review.domain.Review; +import com.funeat.review.presentation.dto.SortingReviewsPageDto; import io.restassured.response.ExtractableResponse; import io.restassured.response.Response; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; @@ -139,6 +156,120 @@ class putMemberProfile_실패_테스트 { } } + + @Nested + class getMemberReviews_성공_테스트 { + + @Test + void 사용자가_작성한_리뷰를_조회하다() { + // given + final var member1 = 멤버_멤버1_생성(); + final var member2 = 멤버_멤버2_생성(); + 복수_멤버_저장(member1, member2); + + final var category = 카테고리_즉석조리_생성(); + 단일_카테고리_저장(category); + + final var product1 = 상품_삼각김밥_가격1000원_평점5점_생성(category); + final var product2 = 상품_삼각김밥_가격2000원_평점3점_생성(category); + final var product3 = 상품_삼각김밥_가격2000원_평점1점_생성(category); + 복수_상품_저장(product1, product2, product3); + + final var review1_1 = 리뷰_이미지test2_평점2점_재구매X_생성(member1, product3, 0L); + + final var review2_1 = 리뷰_이미지test1_평점1점_재구매X_생성(member1, product2, 0L); + final var review2_2 = 리뷰_이미지test1_평점1점_재구매X_생성(member2, product2, 0L); + + final var review3_1 = 리뷰_이미지test3_평점3점_재구매O_생성(member1, product1, 0L); + final var review3_2 = 리뷰_이미지test3_평점3점_재구매O_생성(member2, product1, 0L); + 복수_리뷰_저장(review1_1, review2_1, review2_2, review3_1, review3_2); + + final var member1SortedReviews = List.of(review3_1, review2_1, review1_1); + + final var loginCookie = 로그인_쿠키를_얻는다(); + + // when + final var response = 사용자_리뷰_조회_요청(loginCookie, "createdAt,desc", 0); + final var page = new SortingReviewsPageDto(3L, 1L, true, true, 0L, 10L); + + // then + STATUS_CODE를_검증한다(response, 정상_처리); + 사용자_리뷰_목록_조회_결과를_검증한다(response, member1SortedReviews, page); + } + + @Test + void 사용자가_작성한_리뷰가_없을때_리뷰는_빈상태로_조회된다() { + // given + final var member1 = 멤버_멤버1_생성(); + final var member2 = 멤버_멤버2_생성(); + 복수_멤버_저장(member1, member2); + + final var category = 카테고리_즉석조리_생성(); + 단일_카테고리_저장(category); + + final var product1 = 상품_삼각김밥_가격1000원_평점5점_생성(category); + final var product2 = 상품_삼각김밥_가격2000원_평점3점_생성(category); + final var product3 = 상품_삼각김밥_가격2000원_평점1점_생성(category); + 복수_상품_저장(product1, product2, product3); + + final var review1_1 = 리뷰_이미지test2_평점2점_재구매X_생성(member2, product3, 0L); + final var review1_2 = 리뷰_이미지test3_평점3점_재구매O_생성(member2, product1, 0L); + 복수_리뷰_저장(review1_1, review1_2); + + final var loginCookie = 로그인_쿠키를_얻는다(); + + // when + final var response = 사용자_리뷰_조회_요청(loginCookie, "createdAt,desc", 0); + final var page = new SortingReviewsPageDto(0L, 0L, true, true, 0L, 10L); + + // then + final var actualReviews = response.jsonPath().getList("reviews", MemberReviewDto.class); + final var expectedReviews = Collections.emptyList(); + + STATUS_CODE를_검증한다(response, 정상_처리); + 페이지를_검증한다(response, page); + assertThat(actualReviews).usingRecursiveComparison() + .isEqualTo(expectedReviews); + } + } + + @Nested + class getMemberReviews_실패_테스트 { + + @Test + void 로그인하지_않은_사용자가_작성한_리뷰를_조회할때_예외가_발생한다() { + // given & when + final var response = 사용자_리뷰_조회_요청(null, "createdAt,desc", 0); + + // then + STATUS_CODE를_검증한다(response, 인증되지_않음); + RESPONSE_CODE와_MESSAGE를_검증한다(response, LOGIN_MEMBER_NOT_FOUND.getCode(), + LOGIN_MEMBER_NOT_FOUND.getMessage()); + } + } + + private void 사용자_리뷰_목록_조회_결과를_검증한다(final ExtractableResponse response, final List reviews, + final SortingReviewsPageDto page) { + 페이지를_검증한다(response, page); + 사용자_리뷰_목록을_검증한다(response, reviews); + } + + private void 페이지를_검증한다(final ExtractableResponse response, final SortingReviewsPageDto expected) { + final var actual = response.jsonPath().getObject("page", ProductsInCategoryPageDto.class); + + assertThat(actual).usingRecursiveComparison().isEqualTo(expected); + } + + private void 사용자_리뷰_목록을_검증한다(final ExtractableResponse response, final List reviews) { + final var expected = reviews.stream() + .map(MemberReviewDto::toDto) + .collect(Collectors.toList()); + final var actual = response.jsonPath().getList("reviews", MemberReviewDto.class); + + assertThat(actual).usingRecursiveComparison() + .isEqualTo(expected); + } + private void RESPONSE_CODE와_MESSAGE를_검증한다(final ExtractableResponse response, final String expectedCode, final String expectedMessage) { assertSoftly(softAssertions -> { diff --git a/backend/src/test/java/com/funeat/acceptance/member/MemberSteps.java b/backend/src/test/java/com/funeat/acceptance/member/MemberSteps.java index ca8d3fed5..1166d642c 100644 --- a/backend/src/test/java/com/funeat/acceptance/member/MemberSteps.java +++ b/backend/src/test/java/com/funeat/acceptance/member/MemberSteps.java @@ -28,4 +28,16 @@ public class MemberSteps { .then() .extract(); } + + public static ExtractableResponse 사용자_리뷰_조회_요청(final String loginCookie, final String sort, + final Integer page) { + return given() + .when() + .cookie("JSESSIONID", loginCookie) + .queryParam("sort", sort) + .queryParam("page", page) + .get("/api/members/reviews") + .then() + .extract(); + } } diff --git a/backend/src/test/java/com/funeat/review/application/ReviewServiceTest.java b/backend/src/test/java/com/funeat/review/application/ReviewServiceTest.java index 0f0b49b52..a920194c5 100644 --- a/backend/src/test/java/com/funeat/review/application/ReviewServiceTest.java +++ b/backend/src/test/java/com/funeat/review/application/ReviewServiceTest.java @@ -12,7 +12,12 @@ import static com.funeat.fixture.PageFixture.페이지요청_평점_오름차순_생성; import static com.funeat.fixture.ProductFixture.상품_삼각김밥_가격1000원_평점2점_생성; import static com.funeat.fixture.ProductFixture.상품_삼각김밥_가격1000원_평점3점_생성; +import static com.funeat.fixture.ProductFixture.상품_삼각김밥_가격1000원_평점5점_생성; +import static com.funeat.fixture.ProductFixture.상품_삼각김밥_가격2000원_평점1점_생성; +import static com.funeat.fixture.ProductFixture.상품_삼각김밥_가격2000원_평점3점_생성; +import static com.funeat.fixture.ReviewFixture.리뷰_이미지test1_평점1점_재구매X_생성; import static com.funeat.fixture.ReviewFixture.리뷰_이미지test2_평점2점_재구매O_생성; +import static com.funeat.fixture.ReviewFixture.리뷰_이미지test2_평점2점_재구매X_생성; import static com.funeat.fixture.ReviewFixture.리뷰_이미지test3_평점3점_재구매O_생성; import static com.funeat.fixture.ReviewFixture.리뷰_이미지test3_평점3점_재구매X_생성; import static com.funeat.fixture.ReviewFixture.리뷰_이미지test4_평점4점_재구매O_생성; @@ -26,11 +31,13 @@ import static org.assertj.core.api.SoftAssertions.assertSoftly; import com.funeat.common.ServiceTest; +import com.funeat.member.dto.MemberReviewDto; import com.funeat.member.exception.MemberException.MemberNotFoundException; import com.funeat.product.exception.ProductException.ProductNotFoundException; import com.funeat.review.domain.Review; import com.funeat.review.exception.ReviewException.ReviewNotFoundException; import com.funeat.review.presentation.dto.SortingReviewDto; +import com.funeat.review.presentation.dto.SortingReviewsPageDto; import com.funeat.tag.domain.Tag; import java.util.List; import java.util.stream.Collectors; @@ -521,6 +528,65 @@ class sortingReviews_실패_테스트 { } } + @Nested + class findReviewByMember_성공_테스트 { + + @Test + void 사용자가_작성한_리뷰를_조회한다() { + // given + final var member1 = 멤버_멤버1_생성(); + final var member2 = 멤버_멤버2_생성(); + 복수_멤버_저장(member1, member2); + + final var category = 카테고리_즉석조리_생성(); + 단일_카테고리_저장(category); + + final var product1 = 상품_삼각김밥_가격1000원_평점5점_생성(category); + final var product2 = 상품_삼각김밥_가격2000원_평점3점_생성(category); + final var product3 = 상품_삼각김밥_가격2000원_평점1점_생성(category); + 복수_상품_저장(product1, product2, product3); + + final var review1_1 = 리뷰_이미지test2_평점2점_재구매X_생성(member1, product3, 0L); + + final var review2_1 = 리뷰_이미지test1_평점1점_재구매X_생성(member1, product2, 0L); + final var review2_2 = 리뷰_이미지test1_평점1점_재구매X_생성(member2, product2, 0L); + + final var review3_1 = 리뷰_이미지test3_평점3점_재구매O_생성(member1, product1, 0L); + final var review3_2 = 리뷰_이미지test3_평점3점_재구매O_생성(member2, product1, 0L); + 복수_리뷰_저장(review1_1, review2_1, review2_2, review3_1, review3_2); + + // when + final var page = 페이지요청_생성_시간_내림차순_생성(0, 10); + final var member1Id = member1.getId(); + final var result = reviewService.findReviewByMember(member1Id, page); + + // then + final var expectedReviews = List.of(review3_1, review2_1, review1_1); + final var expectedReviewDtos = expectedReviews.stream() + .map(MemberReviewDto::toDto) + .collect(Collectors.toList()); + final var expectedPage = new SortingReviewsPageDto(3L, 1L, true, true, 0L, 10L); + + assertThat(result.getReviews()).usingRecursiveComparison().isEqualTo(expectedReviewDtos); + assertThat(result.getPage()).usingRecursiveComparison().isEqualTo(expectedPage); + } + } + + @Nested + class findReviewByMember_실패_테스트 { + + @Test + void 존재하지_않은_사용자가_작성한_리뷰를_조회할때_예외가_발생한다() { + // given + final var notExistMemberId = 999999L; + final var page = 페이지요청_생성_시간_내림차순_생성(0, 10); + + // when & then + assertThatThrownBy(() -> reviewService.findReviewByMember(notExistMemberId, page)) + .isInstanceOf(MemberNotFoundException.class); + } + } + private List 태그_아이디_변환(final Tag... tags) { return Stream.of(tags) .map(Tag::getId) From 925767dcc9fadc9268952ba8b502f985ed48c769 Mon Sep 17 00:00:00 2001 From: wugawuga Date: Sun, 13 Aug 2023 21:53:48 +0900 Subject: [PATCH 2/4] =?UTF-8?q?refactor:=20=EB=A6=AC=EB=B7=B0=20=EB=B0=98?= =?UTF-8?q?=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../member/MemberAcceptanceTest.java | 25 ++++++++----------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/backend/src/test/java/com/funeat/acceptance/member/MemberAcceptanceTest.java b/backend/src/test/java/com/funeat/acceptance/member/MemberAcceptanceTest.java index 684d1417b..be3223ef3 100644 --- a/backend/src/test/java/com/funeat/acceptance/member/MemberAcceptanceTest.java +++ b/backend/src/test/java/com/funeat/acceptance/member/MemberAcceptanceTest.java @@ -28,7 +28,6 @@ import com.funeat.member.dto.MemberRequest; import com.funeat.member.dto.MemberReviewDto; import com.funeat.product.dto.ProductsInCategoryPageDto; -import com.funeat.review.domain.Review; import com.funeat.review.presentation.dto.SortingReviewsPageDto; import io.restassured.response.ExtractableResponse; import io.restassured.response.Response; @@ -176,10 +175,8 @@ class getMemberReviews_성공_테스트 { 복수_상품_저장(product1, product2, product3); final var review1_1 = 리뷰_이미지test2_평점2점_재구매X_생성(member1, product3, 0L); - final var review2_1 = 리뷰_이미지test1_평점1점_재구매X_생성(member1, product2, 0L); final var review2_2 = 리뷰_이미지test1_평점1점_재구매X_생성(member2, product2, 0L); - final var review3_1 = 리뷰_이미지test3_평점3점_재구매O_생성(member1, product1, 0L); final var review3_2 = 리뷰_이미지test3_평점3점_재구매O_생성(member2, product1, 0L); 복수_리뷰_저장(review1_1, review2_1, review2_2, review3_1, review3_2); @@ -193,8 +190,12 @@ class getMemberReviews_성공_테스트 { final var page = new SortingReviewsPageDto(3L, 1L, true, true, 0L, 10L); // then + final var expectedReviews = member1SortedReviews.stream() + .map(MemberReviewDto::toDto) + .collect(Collectors.toList()); + STATUS_CODE를_검증한다(response, 정상_처리); - 사용자_리뷰_목록_조회_결과를_검증한다(response, member1SortedReviews, page); + 사용자_리뷰_목록_조회_결과를_검증한다(response, expectedReviews, page); } @Test @@ -223,13 +224,10 @@ class getMemberReviews_성공_테스트 { final var page = new SortingReviewsPageDto(0L, 0L, true, true, 0L, 10L); // then - final var actualReviews = response.jsonPath().getList("reviews", MemberReviewDto.class); final var expectedReviews = Collections.emptyList(); STATUS_CODE를_검증한다(response, 정상_처리); - 페이지를_검증한다(response, page); - assertThat(actualReviews).usingRecursiveComparison() - .isEqualTo(expectedReviews); + 사용자_리뷰_목록_조회_결과를_검증한다(response, expectedReviews, page); } } @@ -248,8 +246,8 @@ class getMemberReviews_실패_테스트 { } } - private void 사용자_리뷰_목록_조회_결과를_검증한다(final ExtractableResponse response, final List reviews, - final SortingReviewsPageDto page) { + private void 사용자_리뷰_목록_조회_결과를_검증한다(final ExtractableResponse response, final List reviews, + final SortingReviewsPageDto page) { 페이지를_검증한다(response, page); 사용자_리뷰_목록을_검증한다(response, reviews); } @@ -260,14 +258,11 @@ class getMemberReviews_실패_테스트 { assertThat(actual).usingRecursiveComparison().isEqualTo(expected); } - private void 사용자_리뷰_목록을_검증한다(final ExtractableResponse response, final List reviews) { - final var expected = reviews.stream() - .map(MemberReviewDto::toDto) - .collect(Collectors.toList()); + private void 사용자_리뷰_목록을_검증한다(final ExtractableResponse response, final List expectedReviews) { final var actual = response.jsonPath().getList("reviews", MemberReviewDto.class); assertThat(actual).usingRecursiveComparison() - .isEqualTo(expected); + .isEqualTo(expectedReviews); } private void RESPONSE_CODE와_MESSAGE를_검증한다(final ExtractableResponse response, final String expectedCode, From 8c54c932dc3fe0d239e59b098e8571a0995a6d32 Mon Sep 17 00:00:00 2001 From: wugawuga Date: Mon, 14 Aug 2023 13:37:17 +0900 Subject: [PATCH 3/4] =?UTF-8?q?refactor:=20=EB=A9=94=EC=86=8C=EB=93=9C?= =?UTF-8?q?=EB=AA=85=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../funeat/acceptance/member/MemberAcceptanceTest.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/backend/src/test/java/com/funeat/acceptance/member/MemberAcceptanceTest.java b/backend/src/test/java/com/funeat/acceptance/member/MemberAcceptanceTest.java index be3223ef3..590bc84b5 100644 --- a/backend/src/test/java/com/funeat/acceptance/member/MemberAcceptanceTest.java +++ b/backend/src/test/java/com/funeat/acceptance/member/MemberAcceptanceTest.java @@ -195,7 +195,7 @@ class getMemberReviews_성공_테스트 { .collect(Collectors.toList()); STATUS_CODE를_검증한다(response, 정상_처리); - 사용자_리뷰_목록_조회_결과를_검증한다(response, expectedReviews, page); + 사용자_리뷰_목록을_검증한다(response, expectedReviews, page); } @Test @@ -227,7 +227,7 @@ class getMemberReviews_성공_테스트 { final var expectedReviews = Collections.emptyList(); STATUS_CODE를_검증한다(response, 정상_처리); - 사용자_리뷰_목록_조회_결과를_검증한다(response, expectedReviews, page); + 사용자_리뷰_목록을_검증한다(response, expectedReviews, page); } } @@ -246,8 +246,8 @@ class getMemberReviews_실패_테스트 { } } - private void 사용자_리뷰_목록_조회_결과를_검증한다(final ExtractableResponse response, final List reviews, - final SortingReviewsPageDto page) { + private void 사용자_리뷰_목록을_검증한다(final ExtractableResponse response, final List reviews, + final SortingReviewsPageDto page) { 페이지를_검증한다(response, page); 사용자_리뷰_목록을_검증한다(response, reviews); } From 90d6c6699f02badb3a344a5d0fbafc125358c0f3 Mon Sep 17 00:00:00 2001 From: wugawuga Date: Mon, 14 Aug 2023 15:55:22 +0900 Subject: [PATCH 4/4] =?UTF-8?q?refactor:=20=EB=A6=AC=EB=B7=B0=20=EB=B0=98?= =?UTF-8?q?=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/funeat/member/presentation/MemberApiController.java | 3 ++- .../com/funeat/acceptance/member/MemberAcceptanceTest.java | 3 ++- .../funeat/acceptance/product/ProductAcceptanceTest.java | 3 ++- .../com/funeat/review/application/ReviewServiceTest.java | 6 ++++-- 4 files changed, 10 insertions(+), 5 deletions(-) diff --git a/backend/src/main/java/com/funeat/member/presentation/MemberApiController.java b/backend/src/main/java/com/funeat/member/presentation/MemberApiController.java index f49fe8003..93375ab97 100644 --- a/backend/src/main/java/com/funeat/member/presentation/MemberApiController.java +++ b/backend/src/main/java/com/funeat/member/presentation/MemberApiController.java @@ -49,7 +49,8 @@ public ResponseEntity putMemberProfile(@AuthenticationPrincipal final Logi } @GetMapping("/reviews") - public ResponseEntity getMemberReview(final LoginInfo loginInfo, final Pageable pageable) { + public ResponseEntity getMemberReview(@AuthenticationPrincipal final LoginInfo loginInfo, + final Pageable pageable) { final MemberReviewsResponse response = reviewService.findReviewByMember(loginInfo.getId(), pageable); return ResponseEntity.ok().body(response); diff --git a/backend/src/test/java/com/funeat/acceptance/member/MemberAcceptanceTest.java b/backend/src/test/java/com/funeat/acceptance/member/MemberAcceptanceTest.java index 590bc84b5..7a816f7a4 100644 --- a/backend/src/test/java/com/funeat/acceptance/member/MemberAcceptanceTest.java +++ b/backend/src/test/java/com/funeat/acceptance/member/MemberAcceptanceTest.java @@ -255,7 +255,8 @@ class getMemberReviews_실패_테스트 { private void 페이지를_검증한다(final ExtractableResponse response, final SortingReviewsPageDto expected) { final var actual = response.jsonPath().getObject("page", ProductsInCategoryPageDto.class); - assertThat(actual).usingRecursiveComparison().isEqualTo(expected); + assertThat(actual).usingRecursiveComparison() + .isEqualTo(expected); } private void 사용자_리뷰_목록을_검증한다(final ExtractableResponse response, final List expectedReviews) { diff --git a/backend/src/test/java/com/funeat/acceptance/product/ProductAcceptanceTest.java b/backend/src/test/java/com/funeat/acceptance/product/ProductAcceptanceTest.java index 3256a61e9..c43786676 100644 --- a/backend/src/test/java/com/funeat/acceptance/product/ProductAcceptanceTest.java +++ b/backend/src/test/java/com/funeat/acceptance/product/ProductAcceptanceTest.java @@ -568,7 +568,8 @@ class getRankingProducts_성공_테스트 { private void 페이지를_검증한다(final ExtractableResponse response, final SortingReviewsPageDto expected) { final var actual = response.jsonPath().getObject("page", ProductsInCategoryPageDto.class); - assertThat(actual).usingRecursiveComparison().isEqualTo(expected); + assertThat(actual).usingRecursiveComparison() + .isEqualTo(expected); } private void 카테고리별_상품_목록_조회_결과를_검증한다(final ExtractableResponse response, final List products) { diff --git a/backend/src/test/java/com/funeat/review/application/ReviewServiceTest.java b/backend/src/test/java/com/funeat/review/application/ReviewServiceTest.java index a920194c5..c0ac14ef8 100644 --- a/backend/src/test/java/com/funeat/review/application/ReviewServiceTest.java +++ b/backend/src/test/java/com/funeat/review/application/ReviewServiceTest.java @@ -567,8 +567,10 @@ class findReviewByMember_성공_테스트 { .collect(Collectors.toList()); final var expectedPage = new SortingReviewsPageDto(3L, 1L, true, true, 0L, 10L); - assertThat(result.getReviews()).usingRecursiveComparison().isEqualTo(expectedReviewDtos); - assertThat(result.getPage()).usingRecursiveComparison().isEqualTo(expectedPage); + assertThat(result.getReviews()).usingRecursiveComparison() + .isEqualTo(expectedReviewDtos); + assertThat(result.getPage()).usingRecursiveComparison() + .isEqualTo(expectedPage); } }