diff --git a/src/main/java/com/example/eightyage/domain/product/entity/Category.java b/src/main/java/com/example/eightyage/domain/product/category/Category.java similarity index 90% rename from src/main/java/com/example/eightyage/domain/product/entity/Category.java rename to src/main/java/com/example/eightyage/domain/product/category/Category.java index 044799d..12c9345 100644 --- a/src/main/java/com/example/eightyage/domain/product/entity/Category.java +++ b/src/main/java/com/example/eightyage/domain/product/category/Category.java @@ -1,4 +1,4 @@ -package com.example.eightyage.domain.product.entity; +package com.example.eightyage.domain.product.category; public enum Category { SKINCARE("스킨케어"), diff --git a/src/main/java/com/example/eightyage/domain/product/controller/ProductController.java b/src/main/java/com/example/eightyage/domain/product/controller/ProductController.java index 54c28ed..f44cbd4 100644 --- a/src/main/java/com/example/eightyage/domain/product/controller/ProductController.java +++ b/src/main/java/com/example/eightyage/domain/product/controller/ProductController.java @@ -6,7 +6,7 @@ import com.example.eightyage.domain.product.dto.response.ProductSaveResponseDto; import com.example.eightyage.domain.product.dto.response.ProductSearchResponseDto; import com.example.eightyage.domain.product.dto.response.ProductUpdateResponseDto; -import com.example.eightyage.domain.product.entity.Category; +import com.example.eightyage.domain.product.category.Category; import com.example.eightyage.domain.product.service.ProductService; import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; @@ -46,8 +46,8 @@ public ResponseEntity updateProduct( // 제품 단건 조회 @GetMapping("/v1/products/{productId}") - public ResponseEntity getProduct(@PathVariable Long productId){ - ProductGetResponseDto responseDto = productService.findProductById(productId); + public ResponseEntity findProduct(@PathVariable Long productId){ + ProductGetResponseDto responseDto = productService.getProductById(productId); return ResponseEntity.ok(responseDto); } diff --git a/src/main/java/com/example/eightyage/domain/product/dto/request/ProductSaveRequestDto.java b/src/main/java/com/example/eightyage/domain/product/dto/request/ProductSaveRequestDto.java index c8d2a04..a7cd103 100644 --- a/src/main/java/com/example/eightyage/domain/product/dto/request/ProductSaveRequestDto.java +++ b/src/main/java/com/example/eightyage/domain/product/dto/request/ProductSaveRequestDto.java @@ -1,12 +1,14 @@ package com.example.eightyage.domain.product.dto.request; -import com.example.eightyage.domain.product.entity.Category; +import com.example.eightyage.domain.product.category.Category; import com.example.eightyage.global.dto.ValidationMessage; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; +import lombok.AllArgsConstructor; import lombok.Getter; @Getter +@AllArgsConstructor public class ProductSaveRequestDto { @NotBlank(message= ValidationMessage.NOT_BLANK_PRODUCT_NAME) diff --git a/src/main/java/com/example/eightyage/domain/product/dto/request/ProductUpdateRequestDto.java b/src/main/java/com/example/eightyage/domain/product/dto/request/ProductUpdateRequestDto.java index 5b0e3ab..272fccc 100644 --- a/src/main/java/com/example/eightyage/domain/product/dto/request/ProductUpdateRequestDto.java +++ b/src/main/java/com/example/eightyage/domain/product/dto/request/ProductUpdateRequestDto.java @@ -1,19 +1,16 @@ package com.example.eightyage.domain.product.dto.request; -import com.example.eightyage.domain.product.entity.Category; -import com.example.eightyage.domain.product.entity.SaleState; +import com.example.eightyage.domain.product.category.Category; +import com.example.eightyage.domain.product.salestate.SaleState; +import lombok.AllArgsConstructor; import lombok.Getter; @Getter +@AllArgsConstructor public class ProductUpdateRequestDto { - private String productName; - private Category category; - private String content; - private SaleState saleState; - private Integer price; } diff --git a/src/main/java/com/example/eightyage/domain/product/dto/response/ProductGetResponseDto.java b/src/main/java/com/example/eightyage/domain/product/dto/response/ProductGetResponseDto.java index 4b76fd7..534ae84 100644 --- a/src/main/java/com/example/eightyage/domain/product/dto/response/ProductGetResponseDto.java +++ b/src/main/java/com/example/eightyage/domain/product/dto/response/ProductGetResponseDto.java @@ -1,7 +1,7 @@ package com.example.eightyage.domain.product.dto.response; -import com.example.eightyage.domain.product.entity.Category; -import com.example.eightyage.domain.product.entity.SaleState; +import com.example.eightyage.domain.product.category.Category; +import com.example.eightyage.domain.product.salestate.SaleState; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; @@ -12,18 +12,11 @@ @Builder @AllArgsConstructor public class ProductGetResponseDto { - private final String productName; - private final String content; - private final Category category; - private final Integer price; - private final SaleState saleState; - private final LocalDateTime createdAt; - private final LocalDateTime modifiedAt; } diff --git a/src/main/java/com/example/eightyage/domain/product/dto/response/ProductSaveResponseDto.java b/src/main/java/com/example/eightyage/domain/product/dto/response/ProductSaveResponseDto.java index 552387e..86abc5d 100644 --- a/src/main/java/com/example/eightyage/domain/product/dto/response/ProductSaveResponseDto.java +++ b/src/main/java/com/example/eightyage/domain/product/dto/response/ProductSaveResponseDto.java @@ -1,7 +1,7 @@ package com.example.eightyage.domain.product.dto.response; -import com.example.eightyage.domain.product.entity.Category; -import com.example.eightyage.domain.product.entity.SaleState; +import com.example.eightyage.domain.product.category.Category; +import com.example.eightyage.domain.product.salestate.SaleState; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; @@ -12,18 +12,11 @@ @Builder @AllArgsConstructor public class ProductSaveResponseDto { - private final String productName; - private final Category category; - private final Integer price; - private final String content; - private final SaleState saleState; - private final LocalDateTime createdAt; - private final LocalDateTime modifiedAt; } diff --git a/src/main/java/com/example/eightyage/domain/product/dto/response/ProductSearchResponseDto.java b/src/main/java/com/example/eightyage/domain/product/dto/response/ProductSearchResponseDto.java index d52d526..3205518 100644 --- a/src/main/java/com/example/eightyage/domain/product/dto/response/ProductSearchResponseDto.java +++ b/src/main/java/com/example/eightyage/domain/product/dto/response/ProductSearchResponseDto.java @@ -1,6 +1,6 @@ package com.example.eightyage.domain.product.dto.response; -import com.example.eightyage.domain.product.entity.Category; +import com.example.eightyage.domain.product.category.Category; import com.fasterxml.jackson.annotation.JsonFormat; import lombok.Builder; import lombok.Getter; diff --git a/src/main/java/com/example/eightyage/domain/product/dto/response/ProductUpdateResponseDto.java b/src/main/java/com/example/eightyage/domain/product/dto/response/ProductUpdateResponseDto.java index a2bf8f4..d44aea6 100644 --- a/src/main/java/com/example/eightyage/domain/product/dto/response/ProductUpdateResponseDto.java +++ b/src/main/java/com/example/eightyage/domain/product/dto/response/ProductUpdateResponseDto.java @@ -1,7 +1,7 @@ package com.example.eightyage.domain.product.dto.response; -import com.example.eightyage.domain.product.entity.Category; -import com.example.eightyage.domain.product.entity.SaleState; +import com.example.eightyage.domain.product.category.Category; +import com.example.eightyage.domain.product.salestate.SaleState; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; @@ -12,18 +12,11 @@ @Builder @AllArgsConstructor public class ProductUpdateResponseDto { - private final String productName; - private final Integer price; - private final String content; - private final Category category; - private final SaleState saleState; - private final LocalDateTime createdAt; - private final LocalDateTime modifiedAt; } diff --git a/src/main/java/com/example/eightyage/domain/product/entity/Product.java b/src/main/java/com/example/eightyage/domain/product/entity/Product.java index 5f061f9..4c09ac5 100644 --- a/src/main/java/com/example/eightyage/domain/product/entity/Product.java +++ b/src/main/java/com/example/eightyage/domain/product/entity/Product.java @@ -1,8 +1,11 @@ package com.example.eightyage.domain.product.entity; +import com.example.eightyage.domain.product.category.Category; +import com.example.eightyage.domain.product.salestate.SaleState; import com.example.eightyage.domain.review.entity.Review; import com.example.eightyage.global.entity.TimeStamped; import jakarta.persistence.*; +import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; @@ -14,6 +17,7 @@ @Entity @Getter @NoArgsConstructor +@AllArgsConstructor @Table(name = "product", indexes = @Index(name = "index_saleState_category_name", columnList = "saleState, category, name") ) @@ -50,31 +54,31 @@ public Product(String name, Category category, String content, Integer price, Sa this.saleState = saleState; } - public void updateName(String newName){ + public void updateNameIfNotNull(String newName){ if(newName != null){ this.name = newName; } } - public void updateCategory(Category newCategory) { + public void updateCategoryIfNotNull(Category newCategory) { if (newCategory != null) { this.category = newCategory; } } - public void updateContent(String newContent) { + public void updateContentIfNotNull(String newContent) { if (newContent != null) { this.content = newContent; } } - public void updatePrice(Integer newPrice) { + public void updatePriceIfNotNull(Integer newPrice) { if (newPrice != null) { this.price = newPrice; } } - public void updateSaleState(SaleState newSaleState) { + public void updateSaleStateIfNotNull(SaleState newSaleState) { if (newSaleState != null) { this.saleState = newSaleState; } diff --git a/src/main/java/com/example/eightyage/domain/product/entity/SaleState.java b/src/main/java/com/example/eightyage/domain/product/entity/SaleState.java deleted file mode 100644 index e69c789..0000000 --- a/src/main/java/com/example/eightyage/domain/product/entity/SaleState.java +++ /dev/null @@ -1,6 +0,0 @@ -package com.example.eightyage.domain.product.entity; - -public enum SaleState { - FOR_SALE, - SOLD_OUT -} diff --git a/src/main/java/com/example/eightyage/domain/product/repository/ProductBulkRepository.java b/src/main/java/com/example/eightyage/domain/product/repository/ProductBulkRepository.java index 272b3e8..e9818db 100644 --- a/src/main/java/com/example/eightyage/domain/product/repository/ProductBulkRepository.java +++ b/src/main/java/com/example/eightyage/domain/product/repository/ProductBulkRepository.java @@ -1,8 +1,8 @@ package com.example.eightyage.domain.product.repository; -import com.example.eightyage.domain.product.entity.Category; +import com.example.eightyage.domain.product.category.Category; import com.example.eightyage.domain.product.entity.Product; -import com.example.eightyage.domain.product.entity.SaleState; +import com.example.eightyage.domain.product.salestate.SaleState; import lombok.RequiredArgsConstructor; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.stereotype.Repository; diff --git a/src/main/java/com/example/eightyage/domain/product/repository/ProductImageRepository.java b/src/main/java/com/example/eightyage/domain/product/repository/ProductImageRepository.java index a167757..aa2c50e 100644 --- a/src/main/java/com/example/eightyage/domain/product/repository/ProductImageRepository.java +++ b/src/main/java/com/example/eightyage/domain/product/repository/ProductImageRepository.java @@ -1,7 +1,6 @@ package com.example.eightyage.domain.product.repository; import com.example.eightyage.domain.product.entity.ProductImage; -import com.example.eightyage.global.exception.NotFoundException; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; diff --git a/src/main/java/com/example/eightyage/domain/product/repository/ProductRepository.java b/src/main/java/com/example/eightyage/domain/product/repository/ProductRepository.java index 6158523..90baefc 100644 --- a/src/main/java/com/example/eightyage/domain/product/repository/ProductRepository.java +++ b/src/main/java/com/example/eightyage/domain/product/repository/ProductRepository.java @@ -1,7 +1,7 @@ package com.example.eightyage.domain.product.repository; import com.example.eightyage.domain.product.dto.response.ProductSearchResponseDto; -import com.example.eightyage.domain.product.entity.Category; +import com.example.eightyage.domain.product.category.Category; import com.example.eightyage.domain.product.entity.Product; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; diff --git a/src/main/java/com/example/eightyage/domain/product/salestate/SaleState.java b/src/main/java/com/example/eightyage/domain/product/salestate/SaleState.java new file mode 100644 index 0000000..7445bbb --- /dev/null +++ b/src/main/java/com/example/eightyage/domain/product/salestate/SaleState.java @@ -0,0 +1,6 @@ +package com.example.eightyage.domain.product.salestate; + +public enum SaleState { + FOR_SALE, + SOLD_OUT +} diff --git a/src/main/java/com/example/eightyage/domain/product/service/ProductService.java b/src/main/java/com/example/eightyage/domain/product/service/ProductService.java index 052a4a0..01a81a4 100644 --- a/src/main/java/com/example/eightyage/domain/product/service/ProductService.java +++ b/src/main/java/com/example/eightyage/domain/product/service/ProductService.java @@ -3,9 +3,9 @@ import com.example.eightyage.domain.product.dto.request.ProductSaveRequestDto; import com.example.eightyage.domain.product.dto.request.ProductUpdateRequestDto; import com.example.eightyage.domain.product.dto.response.*; -import com.example.eightyage.domain.product.entity.Category; +import com.example.eightyage.domain.product.category.Category; import com.example.eightyage.domain.product.entity.Product; -import com.example.eightyage.domain.product.entity.SaleState; +import com.example.eightyage.domain.product.salestate.SaleState; import com.example.eightyage.domain.product.repository.ProductRepository; import com.example.eightyage.domain.review.entity.Review; import com.example.eightyage.domain.review.repository.ReviewRepository; @@ -57,11 +57,11 @@ public ProductSaveResponseDto saveProduct(ProductSaveRequestDto requestDto) { public ProductUpdateResponseDto updateProduct(Long productId, ProductUpdateRequestDto requestDto) { Product findProduct = findProductByIdOrElseThrow(productId); - findProduct.updateName(requestDto.getProductName()); - findProduct.updateCategory(requestDto.getCategory()); - findProduct.updateContent(requestDto.getContent()); - findProduct.updateSaleState(requestDto.getSaleState()); - findProduct.updatePrice(requestDto.getPrice()); + findProduct.updateNameIfNotNull(requestDto.getProductName()); + findProduct.updateCategoryIfNotNull(requestDto.getCategory()); + findProduct.updateContentIfNotNull(requestDto.getContent()); + findProduct.updateSaleStateIfNotNull(requestDto.getSaleState()); + findProduct.updatePriceIfNotNull(requestDto.getPrice()); return ProductUpdateResponseDto.builder() .productName(findProduct.getName()) @@ -76,7 +76,7 @@ public ProductUpdateResponseDto updateProduct(Long productId, ProductUpdateReque // 제품 단건 조회 @Transactional(readOnly = true) - public ProductGetResponseDto findProductById(Long productId) { + public ProductGetResponseDto getProductById(Long productId) { Product findProduct = findProductByIdOrElseThrow(productId); return ProductGetResponseDto.builder() diff --git a/src/main/java/com/example/eightyage/domain/review/controller/ReviewController.java b/src/main/java/com/example/eightyage/domain/review/controller/ReviewController.java index bdab2e7..ef1d780 100644 --- a/src/main/java/com/example/eightyage/domain/review/controller/ReviewController.java +++ b/src/main/java/com/example/eightyage/domain/review/controller/ReviewController.java @@ -54,16 +54,16 @@ public ResponseEntity updateReview( } // 리뷰 다건 조회 - @GetMapping("/v1/products/{productId}/reviews") - public ResponseEntity> getReviews( - @PathVariable Long productId, + @GetMapping("/v1/reviews") + public ResponseEntity> findReviews( + @RequestParam(required = true) Long productId, @RequestParam(required = false, defaultValue = "score") String orderBy, @RequestParam(defaultValue = "0") int page, @RequestParam(defaultValue = "10") int size ){ PageRequest pageRequest = PageRequest.of(page, size, Sort.by(Sort.Direction.DESC, orderBy)); - Page reviews = reviewService.findReviews(productId, pageRequest); + Page reviews = reviewService.getReviews(productId, pageRequest); return ResponseEntity.ok(reviews); } diff --git a/src/main/java/com/example/eightyage/domain/review/dto/request/ReviewSaveRequestDto.java b/src/main/java/com/example/eightyage/domain/review/dto/request/ReviewSaveRequestDto.java index 9c1d183..5293830 100644 --- a/src/main/java/com/example/eightyage/domain/review/dto/request/ReviewSaveRequestDto.java +++ b/src/main/java/com/example/eightyage/domain/review/dto/request/ReviewSaveRequestDto.java @@ -3,9 +3,11 @@ import com.example.eightyage.global.dto.ValidationMessage; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; +import lombok.AllArgsConstructor; import lombok.Getter; @Getter +@AllArgsConstructor public class ReviewSaveRequestDto { @NotNull(message = ValidationMessage.NOT_NULL_SCORE) diff --git a/src/main/java/com/example/eightyage/domain/review/dto/request/ReviewUpdateRequestDto.java b/src/main/java/com/example/eightyage/domain/review/dto/request/ReviewUpdateRequestDto.java index c6b3e36..5f573ac 100644 --- a/src/main/java/com/example/eightyage/domain/review/dto/request/ReviewUpdateRequestDto.java +++ b/src/main/java/com/example/eightyage/domain/review/dto/request/ReviewUpdateRequestDto.java @@ -2,11 +2,11 @@ import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; +import lombok.AllArgsConstructor; import lombok.Getter; @Getter +@AllArgsConstructor public class ReviewUpdateRequestDto { - private Double score; - private String content; } \ No newline at end of file diff --git a/src/main/java/com/example/eightyage/domain/review/dto/response/ReviewSaveResponseDto.java b/src/main/java/com/example/eightyage/domain/review/dto/response/ReviewSaveResponseDto.java index 03febd7..043cca4 100644 --- a/src/main/java/com/example/eightyage/domain/review/dto/response/ReviewSaveResponseDto.java +++ b/src/main/java/com/example/eightyage/domain/review/dto/response/ReviewSaveResponseDto.java @@ -10,20 +10,12 @@ @Builder @AllArgsConstructor public class ReviewSaveResponseDto { - private final Long id; - private final Long userId; - private final Long productId; - private final String nickname; - private final Double score; - private final String content; - private final LocalDateTime createdAt; - private final LocalDateTime modifiedAt; } diff --git a/src/main/java/com/example/eightyage/domain/review/dto/response/ReviewUpdateResponseDto.java b/src/main/java/com/example/eightyage/domain/review/dto/response/ReviewUpdateResponseDto.java index 9c387e5..6350d3e 100644 --- a/src/main/java/com/example/eightyage/domain/review/dto/response/ReviewUpdateResponseDto.java +++ b/src/main/java/com/example/eightyage/domain/review/dto/response/ReviewUpdateResponseDto.java @@ -10,18 +10,11 @@ @Builder @AllArgsConstructor public class ReviewUpdateResponseDto { - private final Long id; - private final Long userId; - private final String nickname; - private final Double score; - private final String content; - private final LocalDateTime createdAt; - private final LocalDateTime modifiedAt; } \ No newline at end of file diff --git a/src/main/java/com/example/eightyage/domain/review/dto/response/ReviewsGetResponseDto.java b/src/main/java/com/example/eightyage/domain/review/dto/response/ReviewsGetResponseDto.java index c8742ce..9ee2dff 100644 --- a/src/main/java/com/example/eightyage/domain/review/dto/response/ReviewsGetResponseDto.java +++ b/src/main/java/com/example/eightyage/domain/review/dto/response/ReviewsGetResponseDto.java @@ -10,18 +10,11 @@ @Builder @AllArgsConstructor public class ReviewsGetResponseDto { - private final Long id; - private final Long userId; - private final String nickname; - private final Double score; - private final String content; - private final LocalDateTime createdAt; - private final LocalDateTime modifiedAt; } diff --git a/src/main/java/com/example/eightyage/domain/review/entity/Review.java b/src/main/java/com/example/eightyage/domain/review/entity/Review.java index f198fd1..3af3698 100644 --- a/src/main/java/com/example/eightyage/domain/review/entity/Review.java +++ b/src/main/java/com/example/eightyage/domain/review/entity/Review.java @@ -4,6 +4,7 @@ import com.example.eightyage.domain.user.entity.User; import com.example.eightyage.global.entity.TimeStamped; import jakarta.persistence.*; +import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; @@ -11,6 +12,7 @@ @Entity @Getter @NoArgsConstructor +@AllArgsConstructor @Table(name = "review") public class Review extends TimeStamped { @@ -37,13 +39,13 @@ public Review(User user, Product product, Double score, String content) { this.content = content; } - public void updateScore(Double newScore){ + public void updateScoreIfNotNull(Double newScore){ if(newScore != null){ this.score = newScore; } } - public void updateContent(String newContent){ + public void updateContentIfNotNull(String newContent){ if(newContent != null){ this.content = newContent; } diff --git a/src/main/java/com/example/eightyage/domain/review/service/ReviewService.java b/src/main/java/com/example/eightyage/domain/review/service/ReviewService.java index 3d025ef..f7616b2 100644 --- a/src/main/java/com/example/eightyage/domain/review/service/ReviewService.java +++ b/src/main/java/com/example/eightyage/domain/review/service/ReviewService.java @@ -61,8 +61,8 @@ public ReviewUpdateResponseDto updateReview(Long userId, Long reviewId, ReviewUp Review findReview = findReviewByIdOrElseThrow(reviewId); if(findUser.getId().equals(findReview.getUser().getId())){ - findReview.updateScore(requestDto.getScore()); - findReview.updateContent(requestDto.getContent()); + findReview.updateScoreIfNotNull(requestDto.getScore()); + findReview.updateContentIfNotNull(requestDto.getContent()); } else { throw new UnauthorizedException("리뷰를 수정할 권한이 없습니다."); } @@ -80,7 +80,7 @@ public ReviewUpdateResponseDto updateReview(Long userId, Long reviewId, ReviewUp // 리뷰 다건 조회 @Transactional(readOnly = true) - public Page findReviews(Long productId, PageRequest pageRequest) { + public Page getReviews(Long productId, PageRequest pageRequest) { Page reviewPage = reviewRepository.findByProductIdAndProductDeletedAtIsNull(productId, pageRequest); return reviewPage.map(review -> ReviewsGetResponseDto.builder() diff --git a/src/main/java/com/example/eightyage/domain/user/entity/User.java b/src/main/java/com/example/eightyage/domain/user/entity/User.java index 5847eec..13624b5 100644 --- a/src/main/java/com/example/eightyage/domain/user/entity/User.java +++ b/src/main/java/com/example/eightyage/domain/user/entity/User.java @@ -3,10 +3,7 @@ import com.example.eightyage.global.dto.AuthUser; import com.example.eightyage.global.entity.TimeStamped; import jakarta.persistence.*; -import lombok.AccessLevel; -import lombok.Builder; -import lombok.Getter; -import lombok.NoArgsConstructor; +import lombok.*; import java.time.LocalDateTime; diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index f87da91..b7d1ee6 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -12,11 +12,6 @@ server: spring: config: import: optional:file:.env[.properties] - data: - redis: - host: localhost - port: 6379 - application: name: eightyage @@ -37,6 +32,29 @@ spring: use_sql_comments: true dialect: org.hibernate.dialect.MySQLDialect +# cloud: +# aws: +# credentials: +# access-key: ${S3_ACCESS_KEY} +# secret-key: ${S3_SECRET_KEY} +# region: +# static: ap-northeast-2 +# s3: +# bucket: ${S3_BUCKET} +# +#aws: +# credentials: +# access-key: ${S3_ACCESS_KEY} +# secret-key: ${S3_SECRET_KEY} +# region: ap-northeast-2 +# s3: +# bucket: ${S3_BUCKET} + + data: + redis: + host: ${REDIS_HOST} + port: 6379 + jwt: secret: key: ${JWT_SECRET_KEY} diff --git a/src/test/java/com/example/eightyage/domain/product/service/ProductImageServiceTest.java b/src/test/java/com/example/eightyage/domain/product/service/ProductImageServiceTest.java new file mode 100644 index 0000000..77db7ee --- /dev/null +++ b/src/test/java/com/example/eightyage/domain/product/service/ProductImageServiceTest.java @@ -0,0 +1,92 @@ +package com.example.eightyage.domain.product.service; + +import com.example.eightyage.domain.product.entity.Product; +import com.example.eightyage.domain.product.entity.ProductImage; +import com.example.eightyage.domain.product.repository.ProductImageRepository; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.*; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.mock.web.MockMultipartFile; +import org.springframework.test.util.ReflectionTestUtils; +import software.amazon.awssdk.core.sync.RequestBody; +import software.amazon.awssdk.services.s3.S3Client; +import software.amazon.awssdk.services.s3.model.PutObjectRequest; + +import java.util.Optional; +import java.util.function.Consumer; + + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + +@ExtendWith(MockitoExtension.class) +class ProductImageServiceTest { + + @Mock + S3Client s3Client; + + @Mock + ProductImageRepository productImageRepository; + + @Mock + ProductService productService; + + @InjectMocks + ProductImageService productImageService; + + @Mock + ProductImage productImage; + + private MockMultipartFile mockFile; + + @BeforeEach + void setUp(){ + mockFile = new MockMultipartFile( + "file", + "tesst.jpg", + "image/jpeg", + "test image content".getBytes() + ); + + ReflectionTestUtils.setField(productImageService, "bucket", "test-bucket"); + ReflectionTestUtils.setField(productImageService, "region", "us-west-2"); + } + + @Test + void 이미지_업로드_성공(){ + // given + Long productId = 1L; + String bucket = "test-bucket"; + String region = "us-west-2"; + String expectedImageUrl = String.format("https://%s.s3.%s.amazonaws.com/", bucket, region); + + given(productImageRepository.save(any())).willReturn(productImage); + + // when + String imageUrl = productImageService.uploadImage(productId, mockFile); + + // then + assertTrue(imageUrl.startsWith(expectedImageUrl)); + } + + @Test + void 이미지_삭제_성공(){ + // given + Long imageId = 1L; + String imageUrl = "imageUrl-example"; + + given(productImageRepository.findById(any())).willReturn(Optional.of(productImage)); + + // when + productImageService.deleteImage(imageId); + + // then + verify(productImage, times(1)).delete(); + } +} \ No newline at end of file diff --git a/src/test/java/com/example/eightyage/domain/product/service/ProductServiceTest.java b/src/test/java/com/example/eightyage/domain/product/service/ProductServiceTest.java new file mode 100644 index 0000000..da23f05 --- /dev/null +++ b/src/test/java/com/example/eightyage/domain/product/service/ProductServiceTest.java @@ -0,0 +1,122 @@ +package com.example.eightyage.domain.product.service; + +import com.example.eightyage.domain.product.dto.request.ProductSaveRequestDto; +import com.example.eightyage.domain.product.dto.request.ProductUpdateRequestDto; +import com.example.eightyage.domain.product.dto.response.ProductGetResponseDto; +import com.example.eightyage.domain.product.dto.response.ProductSaveResponseDto; +import com.example.eightyage.domain.product.dto.response.ProductUpdateResponseDto; +import com.example.eightyage.domain.product.category.Category; +import com.example.eightyage.domain.product.entity.Product; +import com.example.eightyage.domain.product.salestate.SaleState; +import com.example.eightyage.domain.product.repository.ProductRepository; +import com.example.eightyage.domain.review.entity.Review; +import com.example.eightyage.domain.review.repository.ReviewRepository; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + +@ExtendWith(MockitoExtension.class) +class ProductServiceTest { + + @Mock + ProductRepository productRepository; + + @Mock + ReviewRepository reviewRepository; + + @InjectMocks + ProductService productService; + + @Mock + private Product product; + + @Mock + private Review review1; + + @Mock + private Review review2; + + @Test + void 제품_생성_성공(){ + // given + given(productRepository.save(any())).willReturn(product); + + ProductSaveRequestDto requestDto = new ProductSaveRequestDto("8자 주름 스킨", Category.SKINCARE, "8자 주름을 1자로 펴줍니다.", 20000); + + // when + ProductSaveResponseDto savedProduct = productService.saveProduct(requestDto); + + // then + assertThat(savedProduct.getProductName()).isEqualTo(product.getName()); + } + + @Test + void 제품_수정_성공(){ + // given + Long productId = 1L; + List reviewList = new ArrayList<>(); + reviewList.add(review1); + reviewList.add(review2); + + Product product = new Product(1L, "8자 주름 스킨", Category.SKINCARE, "8자 주름을 1자로 펴주는 퍼펙트 스킨", 20000, SaleState.FOR_SALE, reviewList); + + given(productRepository.findById(any(Long.class))).willReturn(Optional.of(product)); + + ProductUpdateRequestDto requestDto = new ProductUpdateRequestDto("8자 주름 향수", Category.FRAGRANCE, "8자 주름의 은은한 향기", SaleState.FOR_SALE, 50000); + + // when + ProductUpdateResponseDto responseDto = productService.updateProduct(productId, requestDto); + + // then + assertThat(responseDto.getProductName()).isEqualTo(requestDto.getProductName()); + } + + @Test + void 제품_단건_조회_성공(){ + // given + Long productId = 1L; + + given(productRepository.findById(any(Long.class))).willReturn(Optional.of(product)); + + // when + ProductGetResponseDto responseDto = productService.findProductById(productId); + + // then + assertThat(responseDto.getProductName()).isEqualTo(product.getName()); + } + + @Test + void 제품_삭제_성공(){ + // given + Long productId = 1L; + + List reviewList = new ArrayList<>(); + reviewList.add(review1); + reviewList.add(review2); + + given(productRepository.findById(any(Long.class))).willReturn(Optional.of(product)); + given(reviewRepository.findReviewsByProductId(any(Long.class))).willReturn(reviewList); + + // when + productService.deleteProduct(productId); + + // then + verify(review1, times(1)).delete(); + verify(review2, times(1)).delete(); + + verify(product, times(1)).delete(); + } +} \ No newline at end of file diff --git a/src/test/java/com/example/eightyage/domain/review/service/ReviewServiceTest.java b/src/test/java/com/example/eightyage/domain/review/service/ReviewServiceTest.java new file mode 100644 index 0000000..0b4a973 --- /dev/null +++ b/src/test/java/com/example/eightyage/domain/review/service/ReviewServiceTest.java @@ -0,0 +1,188 @@ +package com.example.eightyage.domain.review.service; + +import com.example.eightyage.domain.product.entity.Product; +import com.example.eightyage.domain.product.repository.ProductRepository; +import com.example.eightyage.domain.product.service.ProductService; +import com.example.eightyage.domain.review.dto.request.ReviewSaveRequestDto; +import com.example.eightyage.domain.review.dto.request.ReviewUpdateRequestDto; +import com.example.eightyage.domain.review.dto.response.ReviewSaveResponseDto; +import com.example.eightyage.domain.review.dto.response.ReviewUpdateResponseDto; +import com.example.eightyage.domain.review.dto.response.ReviewsGetResponseDto; +import com.example.eightyage.domain.review.entity.Review; +import com.example.eightyage.domain.review.repository.ReviewRepository; +import com.example.eightyage.domain.user.entity.User; +import com.example.eightyage.domain.user.entity.UserRole; +import com.example.eightyage.domain.user.repository.UserRepository; +import com.example.eightyage.domain.user.service.UserService; +import com.example.eightyage.global.exception.UnauthorizedException; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.boot.autoconfigure.liquibase.LiquibaseProperties; +import org.springframework.data.domain.*; +import org.springframework.data.querydsl.QPageRequest; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.*; + +@ExtendWith(MockitoExtension.class) +class ReviewServiceTest { + + @Mock + ReviewRepository reviewRepository; + + @Mock + UserService userService; + + @Mock + ProductService productService; + + @InjectMocks + ReviewService reviewService; + + @Mock + User user; + + @Mock + Product product; + + @Mock + Review review; + + @Test + void 리뷰_생성_성공(){ + // given + Long userId = 1L; + Long productId = 1L; + Long reviewId = 1L; + + Review review = new Review(reviewId, user, product, 5.0, "8자 주름을 다리미처럼 펴줘요 짱짱"); + given(reviewRepository.save(any())).willReturn(review); + + ReviewSaveRequestDto requestDto = new ReviewSaveRequestDto(5.0, "8자 주름을 다리미처럼 펴줘요 짱짱"); + + // when + ReviewSaveResponseDto responseDto = reviewService.saveReview(userId, productId, requestDto); + + // then + assertEquals(requestDto.getContent(), responseDto.getContent()); + } + + @Test + void 리뷰_수정_작성한_본인이_아닐_경우_실패(){ + // given + Long userId = 2L; + Long reviewId = 1L; + ReviewUpdateRequestDto requestDto = new ReviewUpdateRequestDto(1.0, "쓰다보니 8자 주름이 깊어졌어요. 대실망"); + + User user1 = new User(1L, "ijieun@gmail.com", "이지은B", "password123", UserRole.ROLE_USER); + User user2 = new User(userId, "ijieun@gmail.com", "이지은B", "password123", UserRole.ROLE_USER); + Review review = new Review(reviewId, user1, product, 5.0, "8자 주름을 펴줘요"); + + given(userService.findUserByIdOrElseThrow(any())).willReturn(user2); + given(reviewRepository.findById(any())).willReturn(Optional.of(review)); + + // when + UnauthorizedException exception = assertThrows(UnauthorizedException.class, () -> { + reviewService.updateReview(userId, reviewId, requestDto); + }); + + // then + assertEquals("리뷰를 수정할 권한이 없습니다.", exception.getMessage()); + } + + @Test + void 리뷰_수정_성공(){ + // given + Long userId = 1L; + Long reviewId = 1L; + ReviewUpdateRequestDto requestDto = new ReviewUpdateRequestDto(1.0, "쓰다보니 8자 주름이 깊어졌어요. 대실망"); + + User user = new User(userId, "ijieun@gmail.com", "이지은B", "password123", UserRole.ROLE_USER); + Review review = new Review(reviewId, user, product, 5.0, "8자 주름을 펴줘요"); + + given(userService.findUserByIdOrElseThrow(any())).willReturn(user); + given(reviewRepository.findById(any())).willReturn(Optional.of(review)); + + // when + ReviewUpdateResponseDto responseDto = reviewService.updateReview(userId, reviewId, requestDto); + + // then + assertEquals(requestDto.getContent(), responseDto.getContent()); + } + + @Test + void 리뷰_다건_조회_성공(){ + // given + Long productId = 1L; + PageRequest pageRequest = PageRequest.of(0, 10, Sort.by(Sort.Direction.DESC, "score")); + + Review review1 = new Review(1L, user, product, 5.0, "8자 주름을 펴줘요"); + Review review2 = new Review(1L, user, product, 5.0, "8자 주름을 펴줘요"); + + List reviewList = new ArrayList<>(); + reviewList.add(review1); + reviewList.add(review2); + + Page reviewPage = new PageImpl<>(reviewList, pageRequest, reviewList.size()); + + when(reviewRepository.findByProductIdAndProductDeletedAtIsNull(any(Long.class), eq(pageRequest))).thenReturn(reviewPage); + + // when + Page result = reviewService.findReviews(productId, pageRequest); + + // then + assertNotNull(result); + assertEquals(2, result.getContent().size()); + verify(reviewRepository, times(1)).findByProductIdAndProductDeletedAtIsNull(any(Long.class), eq(pageRequest)); + } + + @Test + void 리뷰_삭제_작성한_본인이_아닐_경우_실패(){ + // given + Long userId = 2L; + Long reviewId = 1L; + + User user1 = new User(1L, "ijieun@gmail.com", "이지은B", "password123", UserRole.ROLE_USER); + User user2 = new User(userId, "ijieun@gmail.com", "이지은B", "password123", UserRole.ROLE_USER); + Review review = new Review(reviewId, user1, product, 5.0, "8자 주름을 펴줘요"); + + given(userService.findUserByIdOrElseThrow(any())).willReturn(user2); + given(reviewRepository.findById(any())).willReturn(Optional.of(review)); + + // when + UnauthorizedException exception = assertThrows(UnauthorizedException.class, () -> { + reviewService.deleteReview(userId, reviewId); + }); + + // then + assertEquals("리뷰를 삭제할 권한이 없습니다.", exception.getMessage()); + } + + @Test + void 리뷰_삭제_성공(){ + // given + Long userId = 1L; + Long reviewId = 1L; + + User user = new User(userId, "ijieun@gmail.com", "이지은B", "password123", UserRole.ROLE_USER); + + given(userService.findUserByIdOrElseThrow(any())).willReturn(user); + given(reviewRepository.findById(any())).willReturn(Optional.of(review)); + given(review.getUser()).willReturn(user); + + // when + reviewService.deleteReview(userId, reviewId); + + // then + verify(review, times(1)).delete(); + } +} \ No newline at end of file