From 1982705382aa656a3fa4ffab284d6a9d83e59739 Mon Sep 17 00:00:00 2001 From: Laptop-Limjihoon Date: Fri, 19 Jan 2024 15:03:55 +0900 Subject: [PATCH 1/4] =?UTF-8?q?refactor=20:=20LikeProduct=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1=EC=9E=90=20Private=20&=20Builder=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/bc1/gream/domain/product/entity/LikeProduct.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/bc1/gream/domain/product/entity/LikeProduct.java b/src/main/java/bc1/gream/domain/product/entity/LikeProduct.java index 13d11c61..da6a8f5c 100644 --- a/src/main/java/bc1/gream/domain/product/entity/LikeProduct.java +++ b/src/main/java/bc1/gream/domain/product/entity/LikeProduct.java @@ -10,6 +10,7 @@ import jakarta.persistence.ManyToOne; import jakarta.persistence.Table; import lombok.AccessLevel; +import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; import org.hibernate.annotations.DynamicInsert; @@ -35,7 +36,8 @@ public class LikeProduct { @JoinColumn(name = "product_id") private Product product; - public LikeProduct(User user, Product product) { + @Builder + private LikeProduct(User user, Product product) { this.user = user; this.product = product; } From bd2fe84e699967e01923f2fd0d486f5f2d6f6635 Mon Sep 17 00:00:00 2001 From: Laptop-Limjihoon Date: Fri, 19 Jan 2024 15:05:45 +0900 Subject: [PATCH 2/4] =?UTF-8?q?refactor=20:=20Product,=20User=20=EC=97=90?= =?UTF-8?q?=EC=84=9C=EC=9D=98=20LikeProduct=20=EC=97=B0=EA=B4=80=EA=B4=80?= =?UTF-8?q?=EA=B3=84=20=EC=BD=9C=EB=A0=89=EC=85=98=EC=9D=84=20List=20->=20?= =?UTF-8?q?Set=EC=9C=BC=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../bc1/gream/domain/product/entity/Product.java | 4 +--- .../java/bc1/gream/domain/user/entity/User.java | 13 +++++++------ .../domain/product/entity/LikeProductTest.java | 2 +- 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/src/main/java/bc1/gream/domain/product/entity/Product.java b/src/main/java/bc1/gream/domain/product/entity/Product.java index 1f993417..f753eed6 100644 --- a/src/main/java/bc1/gream/domain/product/entity/Product.java +++ b/src/main/java/bc1/gream/domain/product/entity/Product.java @@ -12,9 +12,7 @@ import jakarta.persistence.OneToMany; import jakarta.persistence.Table; import jakarta.validation.constraints.NotNull; -import java.util.ArrayList; import java.util.HashSet; -import java.util.List; import java.util.Set; import lombok.AccessLevel; import lombok.Builder; @@ -37,7 +35,7 @@ public class Product extends BaseEntity { @JsonIgnore @OneToMany(mappedBy = "product", targetEntity = LikeProduct.class, cascade = CascadeType.ALL, orphanRemoval = true) - private final List likeProducts = new ArrayList<>(); + private final Set likeProducts = new HashSet<>(); @Id @GeneratedValue(strategy = GenerationType.IDENTITY) diff --git a/src/main/java/bc1/gream/domain/user/entity/User.java b/src/main/java/bc1/gream/domain/user/entity/User.java index 29e28f5e..fc9aee8a 100644 --- a/src/main/java/bc1/gream/domain/user/entity/User.java +++ b/src/main/java/bc1/gream/domain/user/entity/User.java @@ -17,14 +17,13 @@ import jakarta.persistence.Id; import jakarta.persistence.OneToMany; import jakarta.persistence.Table; -import java.util.ArrayList; import java.util.HashSet; -import java.util.List; import java.util.Set; import lombok.AccessLevel; import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; +import org.springframework.transaction.annotation.Transactional; @Getter @Entity @@ -34,15 +33,15 @@ public class User extends BaseEntity { @JsonIgnore @OneToMany(mappedBy = "buyer", targetEntity = Order.class) - private final Set purchasedOrders = new HashSet(); + private final Set purchasedOrders = new HashSet<>(); @JsonIgnore @OneToMany(mappedBy = "seller", targetEntity = Order.class) - private final Set saleOrders = new HashSet(); + private final Set saleOrders = new HashSet<>(); @JsonIgnore @OneToMany(mappedBy = "user", targetEntity = LikeProduct.class, cascade = CascadeType.ALL, orphanRemoval = true) - private final List likeProducts = new ArrayList<>(); + private final Set likeProducts = new HashSet<>(); @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @@ -78,12 +77,14 @@ private User(String loginId, String nickname, String password, UserRole role, Pr this.point = 100000L; } + @Transactional public void addLikeProduct(Product product) { - LikeProduct likeProduct = new LikeProduct(this, product); + LikeProduct likeProduct = LikeProduct.builder().user(this).product(product).build(); product.getLikeProducts().add(likeProduct); this.likeProducts.add(likeProduct); } + @Transactional public void removeLikeProduct(Product product) { LikeProduct likeProduct = this.likeProducts.stream() .filter(lp -> lp.getProduct().equals(product)) diff --git a/src/test/java/bc1/gream/domain/product/entity/LikeProductTest.java b/src/test/java/bc1/gream/domain/product/entity/LikeProductTest.java index c8dd042e..08ddedbf 100644 --- a/src/test/java/bc1/gream/domain/product/entity/LikeProductTest.java +++ b/src/test/java/bc1/gream/domain/product/entity/LikeProductTest.java @@ -49,7 +49,7 @@ void tearDown() { @Test public void 중간조인테이블_복합키_확인() { // GIVEN - LikeProduct likeProduct = new LikeProduct(TEST_USER, TEST_PRODUCT); + LikeProduct likeProduct = LikeProduct.builder().user(TEST_USER).product(TEST_PRODUCT).build(); // WHEN LikeProduct savedLikeProduct = likeProductRepository.save(likeProduct); From f5539345dc90c740ae08b6ccf232285fa2ea9c81 Mon Sep 17 00:00:00 2001 From: Laptop-Limjihoon Date: Fri, 19 Jan 2024 15:06:45 +0900 Subject: [PATCH 3/4] =?UTF-8?q?refactor=20:=20=EC=A4=91=EB=B3=B5=EB=90=9C?= =?UTF-8?q?=20=EA=B4=80=EC=8B=AC=EC=83=81=ED=92=88=20=EB=93=B1=EB=A1=9D?= =?UTF-8?q?=EC=9A=94=EC=B2=AD=EC=97=90=20=EB=8C=80=ED=95=9C=20=EA=B2=80?= =?UTF-8?q?=EC=A6=9D=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/ProductLikeController.java | 2 +- .../service/command/ProductLikeService.java | 8 ++- .../ProductLikeServiceIntegrationTest.java | 53 +++++++++++++++++++ .../command/ProductLikeServiceTest.java | 4 +- .../gream/test/BaseDataRepositoryTest.java | 4 ++ .../bc1/gream/test/BaseIntegrationTest.java | 4 ++ 6 files changed, 72 insertions(+), 3 deletions(-) create mode 100644 src/test/java/bc1/gream/domain/product/service/command/ProductLikeServiceIntegrationTest.java diff --git a/src/main/java/bc1/gream/domain/product/controller/ProductLikeController.java b/src/main/java/bc1/gream/domain/product/controller/ProductLikeController.java index 5101060b..0ceafbe4 100644 --- a/src/main/java/bc1/gream/domain/product/controller/ProductLikeController.java +++ b/src/main/java/bc1/gream/domain/product/controller/ProductLikeController.java @@ -24,7 +24,7 @@ @RestController @RequiredArgsConstructor -@RequestMapping("api/products") +@RequestMapping("/api/products") public class ProductLikeController { private final ProductLikeService productLikeService; diff --git a/src/main/java/bc1/gream/domain/product/service/command/ProductLikeService.java b/src/main/java/bc1/gream/domain/product/service/command/ProductLikeService.java index 1b51d0f0..b0b1fb13 100644 --- a/src/main/java/bc1/gream/domain/product/service/command/ProductLikeService.java +++ b/src/main/java/bc1/gream/domain/product/service/command/ProductLikeService.java @@ -9,11 +9,13 @@ import jakarta.transaction.Transactional; import java.util.List; import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; @Service @RequiredArgsConstructor +@Slf4j public class ProductLikeService { @@ -23,7 +25,11 @@ public class ProductLikeService { @Transactional public void likeProduct(User user, Long productId) { Product product = getProductBy(productId); - user.addLikeProduct(product); + boolean hasNotLikedThisProduct = user.getLikeProducts().stream() + .noneMatch(likeProduct -> likeProduct.getProduct().equals(product)); + if (hasNotLikedThisProduct) { + user.addLikeProduct(product); + } } @Transactional diff --git a/src/test/java/bc1/gream/domain/product/service/command/ProductLikeServiceIntegrationTest.java b/src/test/java/bc1/gream/domain/product/service/command/ProductLikeServiceIntegrationTest.java new file mode 100644 index 00000000..8ef57e8f --- /dev/null +++ b/src/test/java/bc1/gream/domain/product/service/command/ProductLikeServiceIntegrationTest.java @@ -0,0 +1,53 @@ +package bc1.gream.domain.product.service.command; + +import static org.junit.jupiter.api.Assertions.assertTrue; + +import bc1.gream.domain.product.entity.Product; +import bc1.gream.domain.product.repository.LikeProductRepository; +import bc1.gream.domain.user.entity.User; +import bc1.gream.test.BaseIntegrationTest; +import bc1.gream.test.ProductTest; +import bc1.gream.test.UserTest; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.transaction.annotation.Transactional; + +@Disabled("통합테스트는 로컬에서만 실행합니다. 실행 시, SECRET KEY 에 대한 IntelliJ 환경변수를 설정해주어야 합니다.") +@Transactional +class ProductLikeServiceIntegrationTest extends BaseIntegrationTest implements ProductTest, UserTest { + + @Autowired + private ProductLikeService productLikeService; + @Autowired + private LikeProductRepository likeProductRepository; + + @BeforeEach + void setUp() { + setUpBaseIntegrationTest(); + } + + @AfterEach + void tearDown() { + tearDownBaseIntegrationTest(); + } + + @Test + @DisplayName("중복된 관심상품 요청을 검증합니다.") + public void 중복된_관심상품_요청검증() { + // GIVEN + Product product = savedIcedAmericano; + User user = savedBuyer; + + // WHEN + productLikeService.likeProduct(user, product.getId()); + + // THEN + boolean hasNotLikedThisProduct = user.getLikeProducts().stream() + .noneMatch(likeProduct -> likeProduct.getProduct().equals(product)); + assertTrue(hasNotLikedThisProduct); + } +} \ No newline at end of file diff --git a/src/test/java/bc1/gream/domain/product/service/command/ProductLikeServiceTest.java b/src/test/java/bc1/gream/domain/product/service/command/ProductLikeServiceTest.java index 109103df..34236531 100644 --- a/src/test/java/bc1/gream/domain/product/service/command/ProductLikeServiceTest.java +++ b/src/test/java/bc1/gream/domain/product/service/command/ProductLikeServiceTest.java @@ -18,8 +18,10 @@ import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.test.annotation.Rollback; +import org.springframework.test.context.ActiveProfiles; import org.springframework.transaction.annotation.Transactional; +@ActiveProfiles("test") @ExtendWith(MockitoExtension.class) @Rollback(value = true) @Transactional @@ -55,7 +57,7 @@ class ProductLikeServiceTest implements ProductTest, UserTest { // GIVEN given(productRepository.findById(TEST_PRODUCT_ID)).willReturn(Optional.of(TEST_PRODUCT)); User user = User.builder().build(); - LikeProduct likeProduct = new LikeProduct(user, TEST_PRODUCT); + LikeProduct likeProduct = LikeProduct.builder().user(user).product(TEST_PRODUCT).build(); user.getLikeProducts().add(likeProduct); // WHEN diff --git a/src/test/java/bc1/gream/test/BaseDataRepositoryTest.java b/src/test/java/bc1/gream/test/BaseDataRepositoryTest.java index 7ebb090a..368a85ec 100644 --- a/src/test/java/bc1/gream/test/BaseDataRepositoryTest.java +++ b/src/test/java/bc1/gream/test/BaseDataRepositoryTest.java @@ -14,6 +14,7 @@ import bc1.gream.domain.order.entity.Order; import bc1.gream.domain.order.repository.OrderRepository; import bc1.gream.domain.product.entity.Product; +import bc1.gream.domain.product.repository.LikeProductRepository; import bc1.gream.domain.product.repository.ProductRepository; import bc1.gream.domain.sell.entity.Sell; import bc1.gream.domain.sell.repository.SellRepository; @@ -47,6 +48,8 @@ public class BaseDataRepositoryTest implements ProductTest, UserTest, CouponTest @Autowired protected ProductRepository productRepository; @Autowired + protected LikeProductRepository likeProductRepository; + @Autowired protected UserRepository userRepository; @Autowired protected CouponRepository couponRepository; @@ -82,6 +85,7 @@ protected void tearDownBaseDataRepositoryTest() { gifticonRepository.deleteAllInBatch(); orderRepository.deleteAllInBatch(); couponRepository.deleteAllInBatch(); + likeProductRepository.deleteAllInBatch(); userRepository.deleteAllInBatch(); productRepository.deleteAllInBatch(); } diff --git a/src/test/java/bc1/gream/test/BaseIntegrationTest.java b/src/test/java/bc1/gream/test/BaseIntegrationTest.java index e8b0975c..65ae0447 100644 --- a/src/test/java/bc1/gream/test/BaseIntegrationTest.java +++ b/src/test/java/bc1/gream/test/BaseIntegrationTest.java @@ -14,6 +14,7 @@ import bc1.gream.domain.order.entity.Order; import bc1.gream.domain.order.repository.OrderRepository; import bc1.gream.domain.product.entity.Product; +import bc1.gream.domain.product.repository.LikeProductRepository; import bc1.gream.domain.product.repository.ProductRepository; import bc1.gream.domain.sell.entity.Sell; import bc1.gream.domain.sell.repository.SellRepository; @@ -49,6 +50,8 @@ public class BaseIntegrationTest implements ProductTest, UserTest, CouponTest, B @Autowired protected ProductRepository productRepository; @Autowired + protected LikeProductRepository likeProductRepository; + @Autowired protected UserRepository userRepository; @Autowired protected CouponRepository couponRepository; @@ -91,6 +94,7 @@ protected void tearDownBaseIntegrationTest() { gifticonRepository.deleteAllInBatch(); orderRepository.deleteAllInBatch(); couponRepository.deleteAllInBatch(); + likeProductRepository.deleteAllInBatch(); productRepository.deleteAllInBatch(); userRepository.deleteAllInBatch(); } From 26e60e3163e11b22224cae6c184567ab0bebcab7 Mon Sep 17 00:00:00 2001 From: Laptop-Limjihoon Date: Fri, 19 Jan 2024 15:07:20 +0900 Subject: [PATCH 4/4] =?UTF-8?q?refactor=20:=20ProductLikesResponseDto=20?= =?UTF-8?q?=EB=82=B4=EB=B6=80=20=ED=95=84=EB=93=9C=EB=AA=85=20prefix=20?= =?UTF-8?q?=ED=86=B5=EC=9D=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - product prefix 붙이기 --- .../product/dto/response/ProductLikesResponseDto.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/java/bc1/gream/domain/product/dto/response/ProductLikesResponseDto.java b/src/main/java/bc1/gream/domain/product/dto/response/ProductLikesResponseDto.java index 1ff559ab..e1d64b3c 100644 --- a/src/main/java/bc1/gream/domain/product/dto/response/ProductLikesResponseDto.java +++ b/src/main/java/bc1/gream/domain/product/dto/response/ProductLikesResponseDto.java @@ -2,11 +2,11 @@ public record ProductLikesResponseDto( Long id, - String brand, - String name, - String imageUrl, - String description, - Long price + String productBrand, + String productName, + String productImageUrl, + String productDescription, + Long productPrice ) { }