From 4107f8ecff42953088cbe9b5f924f21d65ec1e29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A1=B0=EC=9E=AC=EC=A4=91?= <126754298+m-a-king@users.noreply.github.com> Date: Wed, 11 Sep 2024 11:39:15 +0900 Subject: [PATCH 01/39] =?UTF-8?q?refactor:=20DTO=20req,=20res=20=EA=B5=AC?= =?UTF-8?q?=EB=B6=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Exception/GlobalExceptionHandler.java | 2 +- .../controller/ProductController.java | 19 ++++++----- .../{response => common}/ApiResponseDto.java | 2 +- .../BaseResDto.java} | 4 +-- .../OrderResDto.java} | 6 ++-- .../ProductResDto.java} | 4 +-- .../gc_coffee/service/OrderService.java | 9 +++--- .../gc_coffee/service/OrderServiceImpl.java | 32 ++++++++++--------- .../gc_coffee/service/ProductService.java | 9 +++--- .../gc_coffee/service/ProductServiceImpl.java | 23 ++++++------- 10 files changed, 57 insertions(+), 53 deletions(-) rename src/main/java/org/example/gc_coffee/dto/{response => common}/ApiResponseDto.java (95%) rename src/main/java/org/example/gc_coffee/dto/{BaseDto.java => response/BaseResDto.java} (75%) rename src/main/java/org/example/gc_coffee/dto/{OrderDto.java => response/OrderResDto.java} (65%) rename src/main/java/org/example/gc_coffee/dto/{ProductDto.java => response/ProductResDto.java} (75%) diff --git a/src/main/java/org/example/gc_coffee/Exception/GlobalExceptionHandler.java b/src/main/java/org/example/gc_coffee/Exception/GlobalExceptionHandler.java index 54f862b..09bab0d 100644 --- a/src/main/java/org/example/gc_coffee/Exception/GlobalExceptionHandler.java +++ b/src/main/java/org/example/gc_coffee/Exception/GlobalExceptionHandler.java @@ -1,7 +1,7 @@ package org.example.gc_coffee.Exception; import jakarta.persistence.EntityNotFoundException; -import org.example.gc_coffee.dto.response.ApiResponseDto; +import org.example.gc_coffee.dto.common.ApiResponseDto; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; diff --git a/src/main/java/org/example/gc_coffee/controller/ProductController.java b/src/main/java/org/example/gc_coffee/controller/ProductController.java index ed4cf41..b977c9e 100644 --- a/src/main/java/org/example/gc_coffee/controller/ProductController.java +++ b/src/main/java/org/example/gc_coffee/controller/ProductController.java @@ -1,11 +1,10 @@ package org.example.gc_coffee.controller; import lombok.RequiredArgsConstructor; -import org.example.gc_coffee.dto.ProductDto; -import org.example.gc_coffee.dto.response.ApiResponseDto; +import org.example.gc_coffee.dto.request.ProductReqDto; +import org.example.gc_coffee.dto.response.ProductResDto; +import org.example.gc_coffee.dto.common.ApiResponseDto; import org.example.gc_coffee.service.ProductService; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import java.util.List; @@ -18,20 +17,20 @@ public class ProductController { private final ProductService productService; @GetMapping("/{name}") - public ApiResponseDto getProductByName(@PathVariable(value = "name") String name) { - ProductDto product = productService.getProductByNames(name); + public ApiResponseDto getProductByName(@PathVariable(value = "name") String name) { + ProductResDto product = productService.getProductByNames(name); return new ApiResponseDto<>("Product retrieved successfully", product); } @GetMapping("/all") - public ApiResponseDto> getAllProducts() { - List products = productService.getAllProducts(); + public ApiResponseDto> getAllProducts() { + List products = productService.getAllProducts(); return new ApiResponseDto<>("All products retrieved successfully", products); } @PostMapping - public ApiResponseDto registerProduct(@RequestBody ProductDto productDto) { - productService.registerProduct(productDto); + public ApiResponseDto registerProduct(@RequestBody ProductReqDto productReqDto) { + productService.registerProduct(productReqDto); return new ApiResponseDto<>(201,"Product registered successfully", null); } } \ No newline at end of file diff --git a/src/main/java/org/example/gc_coffee/dto/response/ApiResponseDto.java b/src/main/java/org/example/gc_coffee/dto/common/ApiResponseDto.java similarity index 95% rename from src/main/java/org/example/gc_coffee/dto/response/ApiResponseDto.java rename to src/main/java/org/example/gc_coffee/dto/common/ApiResponseDto.java index 59e584b..c5c74a4 100644 --- a/src/main/java/org/example/gc_coffee/dto/response/ApiResponseDto.java +++ b/src/main/java/org/example/gc_coffee/dto/common/ApiResponseDto.java @@ -1,4 +1,4 @@ -package org.example.gc_coffee.dto.response; +package org.example.gc_coffee.dto.common; import lombok.Getter; import lombok.NoArgsConstructor; diff --git a/src/main/java/org/example/gc_coffee/dto/BaseDto.java b/src/main/java/org/example/gc_coffee/dto/response/BaseResDto.java similarity index 75% rename from src/main/java/org/example/gc_coffee/dto/BaseDto.java rename to src/main/java/org/example/gc_coffee/dto/response/BaseResDto.java index 2b6bed0..e948039 100644 --- a/src/main/java/org/example/gc_coffee/dto/BaseDto.java +++ b/src/main/java/org/example/gc_coffee/dto/response/BaseResDto.java @@ -1,4 +1,4 @@ -package org.example.gc_coffee.dto; +package org.example.gc_coffee.dto.response; import lombok.*; import lombok.experimental.SuperBuilder; @@ -10,7 +10,7 @@ @NoArgsConstructor @AllArgsConstructor @SuperBuilder -public abstract class BaseDto { +public abstract class BaseResDto { private LocalDateTime createdAt; private LocalDateTime updatedAt; } diff --git a/src/main/java/org/example/gc_coffee/dto/OrderDto.java b/src/main/java/org/example/gc_coffee/dto/response/OrderResDto.java similarity index 65% rename from src/main/java/org/example/gc_coffee/dto/OrderDto.java rename to src/main/java/org/example/gc_coffee/dto/response/OrderResDto.java index 7711b4b..e455159 100644 --- a/src/main/java/org/example/gc_coffee/dto/OrderDto.java +++ b/src/main/java/org/example/gc_coffee/dto/response/OrderResDto.java @@ -1,4 +1,4 @@ -package org.example.gc_coffee.dto; +package org.example.gc_coffee.dto.response; import lombok.*; import lombok.experimental.SuperBuilder; @@ -11,11 +11,11 @@ @NoArgsConstructor @AllArgsConstructor @SuperBuilder -public class OrderDto extends BaseDto { +public class OrderResDto extends BaseResDto { private UUID id; private String email; private String address; private String postcode; private String orderStatus; - private List orderProducts; // 주문 항목 목록 + private List orderProducts; // 주문 항목 목록 } \ No newline at end of file diff --git a/src/main/java/org/example/gc_coffee/dto/ProductDto.java b/src/main/java/org/example/gc_coffee/dto/response/ProductResDto.java similarity index 75% rename from src/main/java/org/example/gc_coffee/dto/ProductDto.java rename to src/main/java/org/example/gc_coffee/dto/response/ProductResDto.java index 352d8b8..3bbcf7b 100644 --- a/src/main/java/org/example/gc_coffee/dto/ProductDto.java +++ b/src/main/java/org/example/gc_coffee/dto/response/ProductResDto.java @@ -1,4 +1,4 @@ -package org.example.gc_coffee.dto; +package org.example.gc_coffee.dto.response; import lombok.*; import lombok.experimental.SuperBuilder; @@ -10,7 +10,7 @@ @NoArgsConstructor @AllArgsConstructor @SuperBuilder -public class ProductDto extends BaseDto { +public class ProductResDto extends BaseResDto { private UUID id; private String name; private String category; diff --git a/src/main/java/org/example/gc_coffee/service/OrderService.java b/src/main/java/org/example/gc_coffee/service/OrderService.java index 46a5eda..c880a1d 100644 --- a/src/main/java/org/example/gc_coffee/service/OrderService.java +++ b/src/main/java/org/example/gc_coffee/service/OrderService.java @@ -1,14 +1,15 @@ package org.example.gc_coffee.service; -import org.example.gc_coffee.dto.OrderDto; +import org.example.gc_coffee.dto.request.OrderReqDto; +import org.example.gc_coffee.dto.response.OrderResDto; import java.util.List; public interface OrderService { - List getOrderByEmail(String email); + List getOrderByEmail(String email); - List getAllOrders(); + List getAllOrders(); - void registerOrder(OrderDto orderDto); + void registerOrder(OrderReqDto orderReqDto); } diff --git a/src/main/java/org/example/gc_coffee/service/OrderServiceImpl.java b/src/main/java/org/example/gc_coffee/service/OrderServiceImpl.java index ae59e0d..71d1c20 100644 --- a/src/main/java/org/example/gc_coffee/service/OrderServiceImpl.java +++ b/src/main/java/org/example/gc_coffee/service/OrderServiceImpl.java @@ -3,8 +3,10 @@ import jakarta.persistence.EntityNotFoundException; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.example.gc_coffee.dto.OrderDto; -import org.example.gc_coffee.dto.OrderProductDto; +import org.example.gc_coffee.dto.request.OrderProductReqDto; +import org.example.gc_coffee.dto.request.OrderReqDto; +import org.example.gc_coffee.dto.response.OrderResDto; +import org.example.gc_coffee.dto.response.OrderProductResDto; import org.example.gc_coffee.entity.Order; import org.example.gc_coffee.entity.OrderProduct; import org.example.gc_coffee.entity.Product; @@ -27,7 +29,7 @@ public class OrderServiceImpl implements OrderService { private final ProductService productService; @Override - public List getOrderByEmail(String email) { + public List getOrderByEmail(String email) { try { // 페치 조인을 사용한 메서드를 호출하여 Order와 연관된 OrderProduct들을 한 번에 가져옴 List orders = orderRepository.findAllByEmailWithOrderProducts(email); @@ -43,7 +45,7 @@ public List getOrderByEmail(String email) { } @Override - public List getAllOrders() { + public List getAllOrders() { try { // 페치 조인을 사용하여 모든 Order와 연관된 OrderProduct를 한 번에 가져옴 List orders = orderRepository.findAllWithOrderProducts(); @@ -60,24 +62,24 @@ public List getAllOrders() { @Override @Transactional - public void registerOrder(OrderDto orderDto) { + public void registerOrder(OrderReqDto orderReqDto) { try { Order order = Order.builder() .id(UUID.randomUUID()) - .email(orderDto.getEmail()) - .address(orderDto.getAddress()) - .postcode(orderDto.getPostcode()) - .orderStatus(orderDto.getOrderStatus()) + .email(orderReqDto.getEmail()) + .address(orderReqDto.getAddress()) + .postcode(orderReqDto.getPostcode()) + .orderStatus("REGISTER") // TODO ENUM .orderProducts(new ArrayList<>()) .build(); - List productIds = orderDto.getOrderProducts().stream() - .map(OrderProductDto::getProductId) + List productIds = orderReqDto.getOrderProductList().stream() + .map(OrderProductReqDto::getProductId) .toList(); Map productMap = productService.getProductByIds(productIds); - orderDto.getOrderProducts().forEach(orderProductDto -> { + orderReqDto.getOrderProductList().forEach(orderProductDto -> { Product product = productMap.get(orderProductDto.getProductId()); if (product == null) { @@ -106,16 +108,16 @@ public void registerOrder(OrderDto orderDto) { } } - private static OrderDto buildOrderDto(Order order) { + private static OrderResDto buildOrderDto(Order order) { try { - return OrderDto.builder() + return OrderResDto.builder() .id(order.getId()) .email(order.getEmail()) .address(order.getAddress()) .postcode(order.getPostcode()) .orderStatus(order.getOrderStatus()) .orderProducts(order.getOrderProducts().stream() - .map(opd -> OrderProductDto.builder() + .map(opd -> OrderProductResDto.builder() .seq(opd.getSeq()) .orderId(opd.getOrder().getId()) .productId(opd.getProduct().getId()) diff --git a/src/main/java/org/example/gc_coffee/service/ProductService.java b/src/main/java/org/example/gc_coffee/service/ProductService.java index 85f62a1..265a22b 100644 --- a/src/main/java/org/example/gc_coffee/service/ProductService.java +++ b/src/main/java/org/example/gc_coffee/service/ProductService.java @@ -1,6 +1,7 @@ package org.example.gc_coffee.service; -import org.example.gc_coffee.dto.ProductDto; +import org.example.gc_coffee.dto.request.ProductReqDto; +import org.example.gc_coffee.dto.response.ProductResDto; import org.example.gc_coffee.entity.Product; import java.util.List; @@ -9,11 +10,11 @@ public interface ProductService { - List getAllProducts(); + List getAllProducts(); - void registerProduct(ProductDto productDto); + void registerProduct(ProductReqDto productReqDto); Map getProductByIds(List productIds); - ProductDto getProductByNames(String name); + ProductResDto getProductByNames(String name); } \ No newline at end of file diff --git a/src/main/java/org/example/gc_coffee/service/ProductServiceImpl.java b/src/main/java/org/example/gc_coffee/service/ProductServiceImpl.java index 2e4f35f..0734c98 100644 --- a/src/main/java/org/example/gc_coffee/service/ProductServiceImpl.java +++ b/src/main/java/org/example/gc_coffee/service/ProductServiceImpl.java @@ -4,7 +4,8 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.example.gc_coffee.Exception.AlreadyExistsException; -import org.example.gc_coffee.dto.ProductDto; +import org.example.gc_coffee.dto.request.ProductReqDto; +import org.example.gc_coffee.dto.response.ProductResDto; import org.example.gc_coffee.entity.Product; import org.example.gc_coffee.repository.ProductRepository; import org.springframework.stereotype.Service; @@ -22,12 +23,12 @@ public class ProductServiceImpl implements ProductService { private final ProductRepository productRepository; @Override - public ProductDto getProductByNames(String name) { + public ProductResDto getProductByNames(String name) { try { Product product = productRepository.findByName(name) .orElseThrow(EntityNotFoundException::new); - return ProductDto.builder() + return ProductResDto.builder() .id(product.getId()) .name(product.getName()) .category(product.getCategory()) @@ -46,12 +47,12 @@ public ProductDto getProductByNames(String name) { } @Override - public List getAllProducts() { + public List getAllProducts() { try { List products = productRepository.findAll(); return products.stream() - .map(product -> ProductDto.builder() + .map(product -> ProductResDto.builder() .id(product.getId()) .name(product.getName()) .category(product.getCategory()) @@ -69,20 +70,20 @@ public List getAllProducts() { // 서비스 클래스 내 메서드 @Override - public void registerProduct(ProductDto productDto) { + public void registerProduct(ProductReqDto productReqDto) { try { // 이미 동일한 이름의 제품이 존재하는지 확인 - boolean exists = productRepository.existsByName(productDto.getName()); + boolean exists = productRepository.existsByName(productReqDto.getName()); if (exists) { throw new AlreadyExistsException("Product with this name already exists."); } Product product = Product.builder() .id(UUID.randomUUID()) // 새 제품 등록이므로 새로운 UUID 생성 - .name(productDto.getName()) - .category(productDto.getCategory()) - .price(productDto.getPrice()) - .description(productDto.getDescription()) + .name(productReqDto.getName()) + .category(productReqDto.getCategory()) + .price(productReqDto.getPrice()) + .description(productReqDto.getDescription()) .build(); productRepository.save(product); From 30cc0c0623769cb3426d512819b9d725b78e82b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A1=B0=EC=9E=AC=EC=A4=91?= <126754298+m-a-king@users.noreply.github.com> Date: Wed, 11 Sep 2024 11:40:15 +0900 Subject: [PATCH 02/39] =?UTF-8?q?feat:=20=EC=A3=BC=EB=AC=B8,=20=EC=83=81?= =?UTF-8?q?=ED=92=88=20entity=20PK=20AutoIncrement?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @GeneratedValue 사용 --- src/main/java/org/example/gc_coffee/entity/Order.java | 2 +- src/main/java/org/example/gc_coffee/entity/Product.java | 7 ++----- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/src/main/java/org/example/gc_coffee/entity/Order.java b/src/main/java/org/example/gc_coffee/entity/Order.java index 5fa3696..44fb4a4 100644 --- a/src/main/java/org/example/gc_coffee/entity/Order.java +++ b/src/main/java/org/example/gc_coffee/entity/Order.java @@ -18,7 +18,7 @@ @Table(name = "orders") public class Order extends BaseEntity { - @Id + @Id @GeneratedValue(strategy = GenerationType.UUID) @Column(name = "order_id", columnDefinition = "BINARY(16)") private UUID id; diff --git a/src/main/java/org/example/gc_coffee/entity/Product.java b/src/main/java/org/example/gc_coffee/entity/Product.java index edff759..dbad0fb 100644 --- a/src/main/java/org/example/gc_coffee/entity/Product.java +++ b/src/main/java/org/example/gc_coffee/entity/Product.java @@ -1,9 +1,6 @@ package org.example.gc_coffee.entity; -import jakarta.persistence.Column; -import jakarta.persistence.Entity; -import jakarta.persistence.Id; -import jakarta.persistence.Table; +import jakarta.persistence.*; import lombok.*; import java.util.UUID; @@ -17,7 +14,7 @@ @Table(name = "products") public class Product extends BaseEntity { - @Id + @Id @GeneratedValue(strategy = GenerationType.UUID) @Column(name = "product_id", columnDefinition = "BINARY(16)") private UUID id; From 0b913f52c274f190dee3fd4b638f7b3a8ad087fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A1=B0=EC=9E=AC=EC=A4=91?= <126754298+m-a-king@users.noreply.github.com> Date: Wed, 11 Sep 2024 11:40:41 +0900 Subject: [PATCH 03/39] =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EB=B3=B4?= =?UTF-8?q?=EB=A5=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/OrderServiceImplTest.java | 29 +++----- .../service/ProductServiceImplTest.java | 72 +++++++++---------- 2 files changed, 46 insertions(+), 55 deletions(-) diff --git a/src/test/java/org/example/gc_coffee/service/OrderServiceImplTest.java b/src/test/java/org/example/gc_coffee/service/OrderServiceImplTest.java index b64a315..f42eb29 100644 --- a/src/test/java/org/example/gc_coffee/service/OrderServiceImplTest.java +++ b/src/test/java/org/example/gc_coffee/service/OrderServiceImplTest.java @@ -1,11 +1,10 @@ package org.example.gc_coffee.service; import jakarta.persistence.EntityNotFoundException; -import org.example.gc_coffee.dto.OrderDto; -import org.example.gc_coffee.dto.OrderProductDto; +import org.example.gc_coffee.dto.request.OrderReqDto; +import org.example.gc_coffee.dto.response.OrderResDto; +import org.example.gc_coffee.dto.response.OrderProductResDto; import org.example.gc_coffee.entity.Order; -import org.example.gc_coffee.entity.OrderProduct; -import org.example.gc_coffee.entity.Product; import org.example.gc_coffee.repository.OrderRepository; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -47,12 +46,12 @@ void testGetOrderByEmail_ShouldReturnOrderDto_WhenOrdersExist() { when(orderRepository.findAllByEmailWithOrderProducts(email)).thenReturn(List.of(order)); // When - List result = orderService.getOrderByEmail(email); + List result = orderService.getOrderByEmail(email); // Then assertNotNull(result); - for (OrderDto orderDto : result) { - assertEquals(email, orderDto.getEmail()); + for (OrderResDto orderResDto : result) { + assertEquals(email, orderResDto.getEmail()); } verify(orderRepository, times(1)).findAllByEmailWithOrderProducts(email); } @@ -60,25 +59,17 @@ void testGetOrderByEmail_ShouldReturnOrderDto_WhenOrdersExist() { @Test void testRegisterOrder_ShouldThrowException_WhenProductNotFound() { // Given - OrderDto orderDto = OrderDto.builder() + OrderReqDto orderReqDto = OrderReqDto.builder() .email("test@example.com") .address("Test Address") .postcode("12345") - .orderStatus("PENDING") - .orderProducts(Collections.singletonList( - OrderProductDto.builder() - .productId(UUID.randomUUID()) - .category("Coffee") - .price(20000L) - .quantity(2) - .build() - )) + .orderProductList(null) .build(); when(productService.getProductByIds(any())).thenReturn(Collections.emptyMap()); // When & Then - assertThrows(EntityNotFoundException.class, () -> orderService.registerOrder(orderDto)); + assertThrows(EntityNotFoundException.class, () -> orderService.registerOrder(orderReqDto)); verify(orderRepository, never()).save(any(Order.class)); } @@ -97,7 +88,7 @@ void testGetAllOrders_ShouldReturnListOfOrderDtos_WhenOrdersExist() { when(orderRepository.findAllWithOrderProducts()).thenReturn(Collections.singletonList(order)); // When - List result = orderService.getAllOrders(); + List result = orderService.getAllOrders(); // Then assertNotNull(result); diff --git a/src/test/java/org/example/gc_coffee/service/ProductServiceImplTest.java b/src/test/java/org/example/gc_coffee/service/ProductServiceImplTest.java index be0785e..462776b 100644 --- a/src/test/java/org/example/gc_coffee/service/ProductServiceImplTest.java +++ b/src/test/java/org/example/gc_coffee/service/ProductServiceImplTest.java @@ -2,7 +2,7 @@ import jakarta.persistence.EntityNotFoundException; import org.example.gc_coffee.Exception.AlreadyExistsException; -import org.example.gc_coffee.dto.ProductDto; +import org.example.gc_coffee.dto.response.ProductResDto; import org.example.gc_coffee.entity.Product; import org.example.gc_coffee.repository.ProductRepository; import org.junit.jupiter.api.Test; @@ -44,7 +44,7 @@ void testGetProductByNames_ShouldReturnProductDto_WhenProductExists() { when(productRepository.findByName(productName)).thenReturn(Optional.of(product)); // When - ProductDto result = productService.getProductByNames(productName); + ProductResDto result = productService.getProductByNames(productName); // Then assertNotNull(result); @@ -63,39 +63,39 @@ void testGetProductByNames_ShouldThrowException_WhenProductNotFound() { verify(productRepository, times(1)).findByName(productName); } - @Test - void testRegisterProduct_ShouldSaveProduct_WhenProductDoesNotExist() { - // Given - ProductDto productDto = ProductDto.builder() - .name("Columbia Quindío") - .category("Coffee Beans") - .price(16000L) - .description("A unique coffee with a white wine fermentation process.") - .build(); - when(productRepository.existsByName(productDto.getName())).thenReturn(false); - - // When - productService.registerProduct(productDto); - - // Then - verify(productRepository, times(1)).save(any(Product.class)); - } - - @Test - void testRegisterProduct_ShouldThrowException_WhenProductAlreadyExists() { - // Given - ProductDto productDto = ProductDto.builder() - .name("Columbia Quindío") - .category("Coffee Beans") - .price(16000L) - .description("A unique coffee with a white wine fermentation process.") - .build(); - when(productRepository.existsByName(productDto.getName())).thenReturn(true); - - // When & Then - assertThrows(AlreadyExistsException.class, () -> productService.registerProduct(productDto)); - verify(productRepository, never()).save(any(Product.class)); - } +// @Test +// void testRegisterProduct_ShouldSaveProduct_WhenProductDoesNotExist() { +// // Given +// ProductResDto productResDto = ProductResDto.builder() +// .name("Columbia Quindío") +// .category("Coffee Beans") +// .price(16000L) +// .description("A unique coffee with a white wine fermentation process.") +// .build(); +// when(productRepository.existsByName(productResDto.getName())).thenReturn(false); +// +// // When +// productService.registerProduct(productResDto); +// +// // Then +// verify(productRepository, times(1)).save(any(Product.class)); +// } +// +// @Test +// void testRegisterProduct_ShouldThrowException_WhenProductAlreadyExists() { +// // Given +// ProductResDto productResDto = ProductResDto.builder() +// .name("Columbia Quindío") +// .category("Coffee Beans") +// .price(16000L) +// .description("A unique coffee with a white wine fermentation process.") +// .build(); +// when(productRepository.existsByName(productResDto.getName())).thenReturn(true); +// +// // When & Then +// assertThrows(AlreadyExistsException.class, () -> productService.registerProduct(productResDto)); +// verify(productRepository, never()).save(any(Product.class)); +// } @Test void testGetAllProducts_ShouldReturnListOfProductDtos_WhenProductsExist() { @@ -111,7 +111,7 @@ void testGetAllProducts_ShouldReturnListOfProductDtos_WhenProductsExist() { when(productRepository.findAll()).thenReturn(Collections.singletonList(product)); // When - List result = productService.getAllProducts(); + List result = productService.getAllProducts(); // Then assertNotNull(result); From debe74791d2eeec9b84f28d398883ebe70bf9ce0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A1=B0=EC=9E=AC=EC=A4=91?= <126754298+m-a-king@users.noreply.github.com> Date: Wed, 11 Sep 2024 11:41:26 +0900 Subject: [PATCH 04/39] feat: Req DTOs Validation check --- build.gradle | 2 ++ .../gc_coffee/dto/OrderProductDto.java | 20 ------------ .../dto/request/OrderProductReqDto.java | 23 ++++++++++++++ .../gc_coffee/dto/request/OrderReqDto.java | 31 +++++++++++++++++++ .../gc_coffee/dto/request/ProductReqDto.java | 21 +++++++++++++ 5 files changed, 77 insertions(+), 20 deletions(-) delete mode 100644 src/main/java/org/example/gc_coffee/dto/OrderProductDto.java create mode 100644 src/main/java/org/example/gc_coffee/dto/request/OrderProductReqDto.java create mode 100644 src/main/java/org/example/gc_coffee/dto/request/OrderReqDto.java create mode 100644 src/main/java/org/example/gc_coffee/dto/request/ProductReqDto.java diff --git a/build.gradle b/build.gradle index e410826..3386ced 100644 --- a/build.gradle +++ b/build.gradle @@ -27,7 +27,9 @@ dependencies { implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'org.springframework.boot:spring-boot-starter-jdbc' implementation 'org.springframework.boot:spring-boot-starter-security' + implementation 'org.springframework.boot:spring-boot-starter-validation' implementation 'org.springframework.boot:spring-boot-starter-web' + compileOnly 'org.projectlombok:lombok' developmentOnly 'org.springframework.boot:spring-boot-devtools' runtimeOnly 'com.mysql:mysql-connector-j' diff --git a/src/main/java/org/example/gc_coffee/dto/OrderProductDto.java b/src/main/java/org/example/gc_coffee/dto/OrderProductDto.java deleted file mode 100644 index 44f803a..0000000 --- a/src/main/java/org/example/gc_coffee/dto/OrderProductDto.java +++ /dev/null @@ -1,20 +0,0 @@ -package org.example.gc_coffee.dto; - -import lombok.*; -import lombok.experimental.SuperBuilder; - -import java.util.UUID; - -@Getter -@ToString -@NoArgsConstructor -@AllArgsConstructor -@SuperBuilder -public class OrderProductDto extends BaseDto { - private Long seq; - private UUID orderId; - private UUID productId; - private String category; - private Long price; - private Integer quantity; -} \ No newline at end of file diff --git a/src/main/java/org/example/gc_coffee/dto/request/OrderProductReqDto.java b/src/main/java/org/example/gc_coffee/dto/request/OrderProductReqDto.java new file mode 100644 index 0000000..982d871 --- /dev/null +++ b/src/main/java/org/example/gc_coffee/dto/request/OrderProductReqDto.java @@ -0,0 +1,23 @@ +package org.example.gc_coffee.dto.request; + +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.*; + +import java.util.UUID; + +@Getter +@Builder +public class OrderProductReqDto { + @NotNull(message = "상품 ID를 입력해주세요.") + private UUID productId; + + @NotBlank(message = "카테고리를 입력해주세요.") + private String category; + + @NotNull(message = "가격을 입력해주세요.") + private Long price; // 클라이언트가 보내면 DB 통신 1회 사라짐 + + @NotNull(message = "수량을 입력해주세요.") + private Integer quantity; +} \ No newline at end of file diff --git a/src/main/java/org/example/gc_coffee/dto/request/OrderReqDto.java b/src/main/java/org/example/gc_coffee/dto/request/OrderReqDto.java new file mode 100644 index 0000000..5f6c5ed --- /dev/null +++ b/src/main/java/org/example/gc_coffee/dto/request/OrderReqDto.java @@ -0,0 +1,31 @@ +package org.example.gc_coffee.dto.request; + +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Pattern; +import lombok.Builder; +import lombok.Getter; + +import java.util.List; + +@Getter +@Builder +public class OrderReqDto { + + @NotBlank(message = "이메일을 입력해주세요.") + @Pattern(regexp="^[0-9a-zA-Z]([-_.]?[0-9a-zA-Z])*@[0-9a-zA-Z]([-_.]?[0-9a-zA-Z])+[.][a-zA-Z]{2,3}$", + message="이메일 주소를 확인해주세요") + private String email; + + @NotBlank(message = "주소 정보를 입력해주세요.") + private String address; + + @NotBlank(message = "우편번호 정보를 입력해주세요.") + private String postcode; + + @NotNull(message = "주문 상품이 없습니다.") + @Valid + private List orderProductList; + +} diff --git a/src/main/java/org/example/gc_coffee/dto/request/ProductReqDto.java b/src/main/java/org/example/gc_coffee/dto/request/ProductReqDto.java new file mode 100644 index 0000000..370f51e --- /dev/null +++ b/src/main/java/org/example/gc_coffee/dto/request/ProductReqDto.java @@ -0,0 +1,21 @@ +package org.example.gc_coffee.dto.request; + +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.*; + +@Getter +@Builder +public class ProductReqDto { + @NotBlank(message = "제품명을 입력해주세요.") + private String name; + + @NotBlank(message = "카테고리를 입력해주세요.") + private String category; + + @NotNull(message = "가격을 입력해주세요.") + private Long price; + + @NotBlank(message = "제품 설명을 입력해주세요.") + private String description; +} \ No newline at end of file From 469d607aa8682b8bf903a0bbfb8fcafc90ac3670 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A1=B0=EC=9E=AC=EC=A4=91?= <126754298+m-a-king@users.noreply.github.com> Date: Wed, 11 Sep 2024 11:42:12 +0900 Subject: [PATCH 05/39] =?UTF-8?q?refactor:=20DTO=20req,=20res=20=EA=B5=AC?= =?UTF-8?q?=EB=B6=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../gc_coffee/controller/OrderController.java | 20 ++++++++++--------- .../dto/response/OrderProductResDto.java | 20 +++++++++++++++++++ 2 files changed, 31 insertions(+), 9 deletions(-) create mode 100644 src/main/java/org/example/gc_coffee/dto/response/OrderProductResDto.java diff --git a/src/main/java/org/example/gc_coffee/controller/OrderController.java b/src/main/java/org/example/gc_coffee/controller/OrderController.java index ea39344..87aef33 100644 --- a/src/main/java/org/example/gc_coffee/controller/OrderController.java +++ b/src/main/java/org/example/gc_coffee/controller/OrderController.java @@ -1,8 +1,10 @@ package org.example.gc_coffee.controller; +import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; -import org.example.gc_coffee.dto.OrderDto; -import org.example.gc_coffee.dto.response.ApiResponseDto; +import org.example.gc_coffee.dto.request.OrderReqDto; +import org.example.gc_coffee.dto.response.OrderResDto; +import org.example.gc_coffee.dto.common.ApiResponseDto; import org.example.gc_coffee.service.OrderService; import org.springframework.web.bind.annotation.*; @@ -16,20 +18,20 @@ public class OrderController { private final OrderService orderService; @GetMapping("/{email}") - public ApiResponseDto> getOrderByEmail(@PathVariable(value = "email") String email) { - List orderDtoList = orderService.getOrderByEmail(email); - return new ApiResponseDto<>("Order retrieved successfully", orderDtoList); + public ApiResponseDto> getOrderByEmail(@PathVariable(value = "email") String email) { + List orderResDtoList = orderService.getOrderByEmail(email); + return new ApiResponseDto<>("Order retrieved successfully", orderResDtoList); } @GetMapping("/all") - public ApiResponseDto> getAllOrder() { - List orders = orderService.getAllOrders(); + public ApiResponseDto> getAllOrder() { + List orders = orderService.getAllOrders(); return new ApiResponseDto<>("Orders retrieved successfully", orders); } @PostMapping - public ApiResponseDto registerOrder(@RequestBody OrderDto orderDto) { - orderService.registerOrder(orderDto); + public ApiResponseDto registerOrder(@RequestBody @Valid OrderReqDto orderReqDto) { + orderService.registerOrder(orderReqDto); return new ApiResponseDto<>(201, "Order registered successfully \n당일 오후 2시 이후의 주문은 다음날 배송을 시작합니다.", null); } } \ No newline at end of file diff --git a/src/main/java/org/example/gc_coffee/dto/response/OrderProductResDto.java b/src/main/java/org/example/gc_coffee/dto/response/OrderProductResDto.java new file mode 100644 index 0000000..c813b29 --- /dev/null +++ b/src/main/java/org/example/gc_coffee/dto/response/OrderProductResDto.java @@ -0,0 +1,20 @@ +package org.example.gc_coffee.dto.response; + +import lombok.*; +import lombok.experimental.SuperBuilder; + +import java.util.UUID; + +@Getter +@ToString +@NoArgsConstructor +@AllArgsConstructor +@SuperBuilder +public class OrderProductResDto extends BaseResDto { + private Long seq; + private UUID orderId; + private UUID productId; + private String category; + private Long price; + private Integer quantity; +} \ No newline at end of file From 578adcfffba8e4e85085949e0f382d73063d955d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A1=B0=EC=9E=AC=EC=A4=91?= <126754298+m-a-king@users.noreply.github.com> Date: Wed, 11 Sep 2024 11:44:12 +0900 Subject: [PATCH 06/39] delete: unUsed import --- .../org/example/gc_coffee/service/OrderServiceImplTest.java | 6 ++++-- .../example/gc_coffee/service/ProductServiceImplTest.java | 2 -- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/test/java/org/example/gc_coffee/service/OrderServiceImplTest.java b/src/test/java/org/example/gc_coffee/service/OrderServiceImplTest.java index f42eb29..beb7525 100644 --- a/src/test/java/org/example/gc_coffee/service/OrderServiceImplTest.java +++ b/src/test/java/org/example/gc_coffee/service/OrderServiceImplTest.java @@ -3,7 +3,6 @@ import jakarta.persistence.EntityNotFoundException; import org.example.gc_coffee.dto.request.OrderReqDto; import org.example.gc_coffee.dto.response.OrderResDto; -import org.example.gc_coffee.dto.response.OrderProductResDto; import org.example.gc_coffee.entity.Order; import org.example.gc_coffee.repository.OrderRepository; import org.junit.jupiter.api.Test; @@ -12,7 +11,10 @@ import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; -import java.util.*; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.UUID; import static org.junit.jupiter.api.Assertions.*; import static org.mockito.ArgumentMatchers.any; diff --git a/src/test/java/org/example/gc_coffee/service/ProductServiceImplTest.java b/src/test/java/org/example/gc_coffee/service/ProductServiceImplTest.java index 462776b..26a4481 100644 --- a/src/test/java/org/example/gc_coffee/service/ProductServiceImplTest.java +++ b/src/test/java/org/example/gc_coffee/service/ProductServiceImplTest.java @@ -1,7 +1,6 @@ package org.example.gc_coffee.service; import jakarta.persistence.EntityNotFoundException; -import org.example.gc_coffee.Exception.AlreadyExistsException; import org.example.gc_coffee.dto.response.ProductResDto; import org.example.gc_coffee.entity.Product; import org.example.gc_coffee.repository.ProductRepository; @@ -17,7 +16,6 @@ import java.util.UUID; import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.*; @ExtendWith(MockitoExtension.class) From 4c0fec8bf0c0b50c4192edb52a2f8b14b6dcc911 Mon Sep 17 00:00:00 2001 From: shmin_98 Date: Wed, 11 Sep 2024 14:29:38 +0900 Subject: [PATCH 07/39] =?UTF-8?q?=EC=8B=A4=ED=96=89=20=EC=8B=9C=EA=B0=84?= =?UTF-8?q?=20=EC=B8=A1=EC=A0=95=20AOP=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [설정 추가 내용] -. AOP 라이브러리 추가 [구현 내용] 1. 패키지 전체 AOP 설정 구현 2. 함수 별 AOP 설정 구현 (어노테이션 활용) --- build.gradle | 1 + .../example/gc_coffee/aspects/ExeTimer.java | 11 +++ .../gc_coffee/aspects/ExecutionTimer.java | 68 +++++++++++++++++++ 3 files changed, 80 insertions(+) create mode 100644 src/main/java/org/example/gc_coffee/aspects/ExeTimer.java create mode 100644 src/main/java/org/example/gc_coffee/aspects/ExecutionTimer.java diff --git a/build.gradle b/build.gradle index e410826..d21aece 100644 --- a/build.gradle +++ b/build.gradle @@ -35,6 +35,7 @@ dependencies { testImplementation 'org.springframework.boot:spring-boot-starter-test' testImplementation 'org.springframework.security:spring-security-test' testRuntimeOnly 'org.junit.platform:junit-platform-launcher' + implementation 'org.springframework.boot:spring-boot-starter-aop' } tasks.named('test') { diff --git a/src/main/java/org/example/gc_coffee/aspects/ExeTimer.java b/src/main/java/org/example/gc_coffee/aspects/ExeTimer.java new file mode 100644 index 0000000..f46b89c --- /dev/null +++ b/src/main/java/org/example/gc_coffee/aspects/ExeTimer.java @@ -0,0 +1,11 @@ +package org.example.gc_coffee.aspects; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE}) +@Retention(RetentionPolicy.RUNTIME) +public @interface ExeTimer { +} \ No newline at end of file diff --git a/src/main/java/org/example/gc_coffee/aspects/ExecutionTimer.java b/src/main/java/org/example/gc_coffee/aspects/ExecutionTimer.java new file mode 100644 index 0000000..1a78a0c --- /dev/null +++ b/src/main/java/org/example/gc_coffee/aspects/ExecutionTimer.java @@ -0,0 +1,68 @@ +package org.example.gc_coffee.aspects; + +import lombok.extern.log4j.Log4j2; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.aspectj.lang.reflect.MethodSignature; +import org.springframework.stereotype.Component; +import org.springframework.util.StopWatch; + +@Log4j2 +@Component +@Aspect +public class ExecutionTimer { + + /* + * @Arund 사용 -> 메서드 실행 전, 후로 시간을 공유해야 하기 때문 + * * org.example.gc_coffee.controller.*.*(..) -> controller 패키지 내의 모든 클래스 및 함수 실행 시 동작 + */ +// @Around("execution(* org.example.gc_coffee.controller.*.*(..))") +// public Object PackageExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable { +// +// StopWatch stopWatch = new StopWatch(); +// +// stopWatch.start(); +// Object result = joinPoint.proceed(); +// stopWatch.stop(); +// +// long totalTimeMillis = stopWatch.getTotalTimeMillis(); +// +// MethodSignature signature = (MethodSignature) joinPoint.getSignature(); +// String methodName = signature.getMethod().getName(); +// +// log.info("실행 메서드: {}, 실행시간 = {}ms", methodName, totalTimeMillis); +// +// return result; +// } + + + + /* + * 조인포인트를 어노테이션으로 설정 + * 시간을 테스트할 함수에 @ExeTimer 작성 + */ +// @Pointcut("@annotation(org.example.gc_coffee.aspects.ExeTimer)") +// private void timer(){}; +// +// // 메서드 실행 전,후로 시간을 공유해야 하기 때문 +// @Around("timer()") +// public Object UnitExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable { +// +// StopWatch stopWatch = new StopWatch(); +// +// stopWatch.start(); +// Object result = joinPoint.proceed(); // 조인포인트의 메서드 실행 +// stopWatch.stop(); +// +// long totalTimeMillis = stopWatch.getTotalTimeMillis(); +// +// MethodSignature signature = (MethodSignature) joinPoint.getSignature(); +// String methodName = signature.getMethod().getName(); +// +// log.info("실행 메서드: {}, 실행시간 = {}ms", methodName, totalTimeMillis); +// +// return result; +// } +} From 54888e0e17c9a7dc61b8367f1e2074adc736b170 Mon Sep 17 00:00:00 2001 From: YeChan Date: Wed, 11 Sep 2024 15:00:19 +0900 Subject: [PATCH 08/39] =?UTF-8?q?=EB=A1=9C=EA=B7=B8=20=EA=B4=80=EB=A6=AC?= =?UTF-8?q?=EB=A5=BC=20=EC=9C=84=ED=95=9C=20xml=20=EC=84=A4=EC=A0=95=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80,=20CONSOLE,=20FILE,=20ERROR=20=EC=97=90=20?= =?UTF-8?q?=EB=8C=80=ED=95=9C=20=EB=A1=9C=EA=B7=B8=20=EA=B4=80=EB=A6=AC=20?= =?UTF-8?q?=EA=B0=80=EB=8A=A5,=20=EB=A1=9C=EA=B7=B8=20=EB=A0=88=EB=B2=A8?= =?UTF-8?q?=EB=B3=84=20=EB=8B=A8=EC=9C=84=20=EC=BB=A4=EC=8A=A4=ED=85=80=20?= =?UTF-8?q?=EC=84=A4=EC=A0=95=20=EC=A7=84=ED=96=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/resources/logback-spring.xml | 104 ++++++++++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100644 src/main/resources/logback-spring.xml diff --git a/src/main/resources/logback-spring.xml b/src/main/resources/logback-spring.xml new file mode 100644 index 0000000..f8ae775 --- /dev/null +++ b/src/main/resources/logback-spring.xml @@ -0,0 +1,104 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ${CONSOLE_LOG_PATTERN} + + + + + + + ${LOG_PATH}/${LOG_FILE_NAME}.log + + + + ${FILE_LOG_PATTERN} + + + + + + ${LOG_PATH}/${LOG_FILE_NAME}.%d{yyyy-MM-dd}_%i.gz + + + 10KB + + + 30 + + 1GB + + + + + + + error + ACCEPT + DENY + + ${LOG_PATH}/${ERR_LOG_FILE_NAME}.log + + ${FILE_LOG_PATTERN} + + + + + + ${LOG_PATH}/${ERR_LOG_FILE_NAME}.%d{yyyy-MM-dd}_%i.log + + + 10KB + + + 60 + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file From 8212e973111c6f75e4ad659717306efbffe3018e Mon Sep 17 00:00:00 2001 From: YeChan Date: Wed, 11 Sep 2024 15:01:01 +0900 Subject: [PATCH 09/39] =?UTF-8?q?=EB=A1=9C=EA=B7=B8=20=EA=B4=80=EB=A6=AC?= =?UTF-8?q?=20=ED=99=98=EA=B2=BD=EC=97=90=20=EB=94=B0=EB=9D=BC=20Profile?= =?UTF-8?q?=20=EC=84=A4=EC=A0=95=20=EC=B6=94=EA=B0=80(local,=20dev)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/resources/application.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index d0754df..0ab7ae2 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -5,6 +5,9 @@ spring: password: ${LOCAL_PASSWORD} driver-class-name: com.mysql.cj.jdbc.Driver + profiles: + active: local # 또는 dev + jpa: show-sql: true # JPA가 실행하는 SQL 쿼리를 출력하도록 설정 properties: From 0707374d288f4b899248d6468d06cdd9b468731a Mon Sep 17 00:00:00 2001 From: shmin Date: Wed, 11 Sep 2024 16:06:54 +0900 Subject: [PATCH 10/39] AOP Rollback --- build.gradle | 1 - .../example/gc_coffee/aspects/ExeTimer.java | 11 --- .../gc_coffee/aspects/ExecutionTimer.java | 68 ------------------- 3 files changed, 80 deletions(-) delete mode 100644 src/main/java/org/example/gc_coffee/aspects/ExeTimer.java delete mode 100644 src/main/java/org/example/gc_coffee/aspects/ExecutionTimer.java diff --git a/build.gradle b/build.gradle index d21aece..e410826 100644 --- a/build.gradle +++ b/build.gradle @@ -35,7 +35,6 @@ dependencies { testImplementation 'org.springframework.boot:spring-boot-starter-test' testImplementation 'org.springframework.security:spring-security-test' testRuntimeOnly 'org.junit.platform:junit-platform-launcher' - implementation 'org.springframework.boot:spring-boot-starter-aop' } tasks.named('test') { diff --git a/src/main/java/org/example/gc_coffee/aspects/ExeTimer.java b/src/main/java/org/example/gc_coffee/aspects/ExeTimer.java deleted file mode 100644 index f46b89c..0000000 --- a/src/main/java/org/example/gc_coffee/aspects/ExeTimer.java +++ /dev/null @@ -1,11 +0,0 @@ -package org.example.gc_coffee.aspects; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE}) -@Retention(RetentionPolicy.RUNTIME) -public @interface ExeTimer { -} \ No newline at end of file diff --git a/src/main/java/org/example/gc_coffee/aspects/ExecutionTimer.java b/src/main/java/org/example/gc_coffee/aspects/ExecutionTimer.java deleted file mode 100644 index 1a78a0c..0000000 --- a/src/main/java/org/example/gc_coffee/aspects/ExecutionTimer.java +++ /dev/null @@ -1,68 +0,0 @@ -package org.example.gc_coffee.aspects; - -import lombok.extern.log4j.Log4j2; -import org.aspectj.lang.ProceedingJoinPoint; -import org.aspectj.lang.annotation.Around; -import org.aspectj.lang.annotation.Aspect; -import org.aspectj.lang.annotation.Pointcut; -import org.aspectj.lang.reflect.MethodSignature; -import org.springframework.stereotype.Component; -import org.springframework.util.StopWatch; - -@Log4j2 -@Component -@Aspect -public class ExecutionTimer { - - /* - * @Arund 사용 -> 메서드 실행 전, 후로 시간을 공유해야 하기 때문 - * * org.example.gc_coffee.controller.*.*(..) -> controller 패키지 내의 모든 클래스 및 함수 실행 시 동작 - */ -// @Around("execution(* org.example.gc_coffee.controller.*.*(..))") -// public Object PackageExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable { -// -// StopWatch stopWatch = new StopWatch(); -// -// stopWatch.start(); -// Object result = joinPoint.proceed(); -// stopWatch.stop(); -// -// long totalTimeMillis = stopWatch.getTotalTimeMillis(); -// -// MethodSignature signature = (MethodSignature) joinPoint.getSignature(); -// String methodName = signature.getMethod().getName(); -// -// log.info("실행 메서드: {}, 실행시간 = {}ms", methodName, totalTimeMillis); -// -// return result; -// } - - - - /* - * 조인포인트를 어노테이션으로 설정 - * 시간을 테스트할 함수에 @ExeTimer 작성 - */ -// @Pointcut("@annotation(org.example.gc_coffee.aspects.ExeTimer)") -// private void timer(){}; -// -// // 메서드 실행 전,후로 시간을 공유해야 하기 때문 -// @Around("timer()") -// public Object UnitExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable { -// -// StopWatch stopWatch = new StopWatch(); -// -// stopWatch.start(); -// Object result = joinPoint.proceed(); // 조인포인트의 메서드 실행 -// stopWatch.stop(); -// -// long totalTimeMillis = stopWatch.getTotalTimeMillis(); -// -// MethodSignature signature = (MethodSignature) joinPoint.getSignature(); -// String methodName = signature.getMethod().getName(); -// -// log.info("실행 메서드: {}, 실행시간 = {}ms", methodName, totalTimeMillis); -// -// return result; -// } -} From 5427ce34a71621eb8a9b78d497d1e2e55e0ad8af Mon Sep 17 00:00:00 2001 From: shmin Date: Wed, 11 Sep 2024 16:11:11 +0900 Subject: [PATCH 11/39] =?UTF-8?q?[=EC=84=A4=EC=A0=95=20=EC=B6=94=EA=B0=80?= =?UTF-8?q?=20=EB=82=B4=EC=9A=A9]=20-.=20AOP=20=EB=9D=BC=EC=9D=B4=EB=B8=8C?= =?UTF-8?q?=EB=9F=AC=EB=A6=AC=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [구현 내용] 1. 패키지 전체 AOP 설정 구현 2. 함수 별 AOP 설정 구현 (어노테이션 활용) --- build.gradle | 1 + .../example/gc_coffee/aspects/ExeTimer.java | 11 +++ .../gc_coffee/aspects/ExecutionTimer.java | 68 +++++++++++++++++++ 3 files changed, 80 insertions(+) create mode 100644 src/main/java/org/example/gc_coffee/aspects/ExeTimer.java create mode 100644 src/main/java/org/example/gc_coffee/aspects/ExecutionTimer.java diff --git a/build.gradle b/build.gradle index e410826..d21aece 100644 --- a/build.gradle +++ b/build.gradle @@ -35,6 +35,7 @@ dependencies { testImplementation 'org.springframework.boot:spring-boot-starter-test' testImplementation 'org.springframework.security:spring-security-test' testRuntimeOnly 'org.junit.platform:junit-platform-launcher' + implementation 'org.springframework.boot:spring-boot-starter-aop' } tasks.named('test') { diff --git a/src/main/java/org/example/gc_coffee/aspects/ExeTimer.java b/src/main/java/org/example/gc_coffee/aspects/ExeTimer.java new file mode 100644 index 0000000..f46b89c --- /dev/null +++ b/src/main/java/org/example/gc_coffee/aspects/ExeTimer.java @@ -0,0 +1,11 @@ +package org.example.gc_coffee.aspects; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE}) +@Retention(RetentionPolicy.RUNTIME) +public @interface ExeTimer { +} \ No newline at end of file diff --git a/src/main/java/org/example/gc_coffee/aspects/ExecutionTimer.java b/src/main/java/org/example/gc_coffee/aspects/ExecutionTimer.java new file mode 100644 index 0000000..1a78a0c --- /dev/null +++ b/src/main/java/org/example/gc_coffee/aspects/ExecutionTimer.java @@ -0,0 +1,68 @@ +package org.example.gc_coffee.aspects; + +import lombok.extern.log4j.Log4j2; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.aspectj.lang.reflect.MethodSignature; +import org.springframework.stereotype.Component; +import org.springframework.util.StopWatch; + +@Log4j2 +@Component +@Aspect +public class ExecutionTimer { + + /* + * @Arund 사용 -> 메서드 실행 전, 후로 시간을 공유해야 하기 때문 + * * org.example.gc_coffee.controller.*.*(..) -> controller 패키지 내의 모든 클래스 및 함수 실행 시 동작 + */ +// @Around("execution(* org.example.gc_coffee.controller.*.*(..))") +// public Object PackageExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable { +// +// StopWatch stopWatch = new StopWatch(); +// +// stopWatch.start(); +// Object result = joinPoint.proceed(); +// stopWatch.stop(); +// +// long totalTimeMillis = stopWatch.getTotalTimeMillis(); +// +// MethodSignature signature = (MethodSignature) joinPoint.getSignature(); +// String methodName = signature.getMethod().getName(); +// +// log.info("실행 메서드: {}, 실행시간 = {}ms", methodName, totalTimeMillis); +// +// return result; +// } + + + + /* + * 조인포인트를 어노테이션으로 설정 + * 시간을 테스트할 함수에 @ExeTimer 작성 + */ +// @Pointcut("@annotation(org.example.gc_coffee.aspects.ExeTimer)") +// private void timer(){}; +// +// // 메서드 실행 전,후로 시간을 공유해야 하기 때문 +// @Around("timer()") +// public Object UnitExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable { +// +// StopWatch stopWatch = new StopWatch(); +// +// stopWatch.start(); +// Object result = joinPoint.proceed(); // 조인포인트의 메서드 실행 +// stopWatch.stop(); +// +// long totalTimeMillis = stopWatch.getTotalTimeMillis(); +// +// MethodSignature signature = (MethodSignature) joinPoint.getSignature(); +// String methodName = signature.getMethod().getName(); +// +// log.info("실행 메서드: {}, 실행시간 = {}ms", methodName, totalTimeMillis); +// +// return result; +// } +} From c2acb4d4a5918ebfa114a80acbcafd7f74081896 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A1=B0=EC=9E=AC=EC=A4=91?= <126754298+m-a-king@users.noreply.github.com> Date: Wed, 11 Sep 2024 16:37:16 +0900 Subject: [PATCH 12/39] =?UTF-8?q?refactor:=20=EC=83=9D=EC=84=B1,=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=20Auditing?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 순수 JPA EntityListener -> Spring AuditingEntityListener --- .../gc_coffee/GcCoffeeApplication.java | 2 ++ .../example/gc_coffee/entity/BaseEntity.java | 29 +++++++++---------- 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/src/main/java/org/example/gc_coffee/GcCoffeeApplication.java b/src/main/java/org/example/gc_coffee/GcCoffeeApplication.java index a7043d2..abbcff6 100644 --- a/src/main/java/org/example/gc_coffee/GcCoffeeApplication.java +++ b/src/main/java/org/example/gc_coffee/GcCoffeeApplication.java @@ -2,7 +2,9 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.data.jpa.repository.config.EnableJpaAuditing; +@EnableJpaAuditing //등록시각, 수정시각을 위한 전체 auditing 활성화를 위한 에노테이션 @SpringBootApplication public class GcCoffeeApplication { diff --git a/src/main/java/org/example/gc_coffee/entity/BaseEntity.java b/src/main/java/org/example/gc_coffee/entity/BaseEntity.java index de228e6..7b98900 100644 --- a/src/main/java/org/example/gc_coffee/entity/BaseEntity.java +++ b/src/main/java/org/example/gc_coffee/entity/BaseEntity.java @@ -1,30 +1,29 @@ package org.example.gc_coffee.entity; -import jakarta.persistence.Column; -import jakarta.persistence.MappedSuperclass; -import jakarta.persistence.PrePersist; -import jakarta.persistence.PreUpdate; +import jakarta.persistence.*; import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; +import org.springframework.data.annotation.CreatedDate; +import org.springframework.data.annotation.LastModifiedDate; +import org.springframework.data.jpa.domain.support.AuditingEntityListener; import java.time.LocalDateTime; -@MappedSuperclass @Getter +@NoArgsConstructor +@MappedSuperclass +@SuperBuilder +@EntityListeners(AuditingEntityListener.class) public abstract class BaseEntity { - @Column(updatable = false) + @CreatedDate + @Column(name = "created_at", nullable = false, updatable = false) private LocalDateTime createdAt; + @LastModifiedDate + @Column(name = "updated_at") private LocalDateTime updatedAt; - @PrePersist - protected void onCreate() { - createdAt = LocalDateTime.now(); - } - - @PreUpdate - protected void onUpdate() { - updatedAt = LocalDateTime.now(); - } } \ No newline at end of file From 7a17e2c5bece8c6292f5e0d97c11b3a1f01a7c12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A1=B0=EC=9E=AC=EC=A4=91?= <126754298+m-a-king@users.noreply.github.com> Date: Wed, 11 Sep 2024 16:44:04 +0900 Subject: [PATCH 13/39] =?UTF-8?q?update:=20DTO=20class=20=EB=A5=BC=20recor?= =?UTF-8?q?d=20=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 service에 있는 factory method를 DTO에게 옮겼습니다 --- .../dto/request/OrderProductReqDto.java | 40 +++++--- .../gc_coffee/dto/request/OrderReqDto.java | 67 +++++++++---- .../gc_coffee/dto/request/ProductReqDto.java | 37 +++++--- .../gc_coffee/dto/response/BaseResDto.java | 16 ---- .../dto/response/OrderProductResDto.java | 47 +++++++--- .../gc_coffee/dto/response/OrderResDto.java | 54 ++++++++--- .../gc_coffee/dto/response/ProductResDto.java | 42 ++++++--- .../gc_coffee/service/OrderServiceImpl.java | 94 +++++++------------ .../gc_coffee/service/ProductServiceImpl.java | 41 ++------ 9 files changed, 244 insertions(+), 194 deletions(-) delete mode 100644 src/main/java/org/example/gc_coffee/dto/response/BaseResDto.java diff --git a/src/main/java/org/example/gc_coffee/dto/request/OrderProductReqDto.java b/src/main/java/org/example/gc_coffee/dto/request/OrderProductReqDto.java index 982d871..d647fd8 100644 --- a/src/main/java/org/example/gc_coffee/dto/request/OrderProductReqDto.java +++ b/src/main/java/org/example/gc_coffee/dto/request/OrderProductReqDto.java @@ -2,22 +2,38 @@ import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; -import lombok.*; +import org.example.gc_coffee.entity.Order; +import org.example.gc_coffee.entity.OrderProduct; +import org.example.gc_coffee.entity.Product; import java.util.UUID; -@Getter -@Builder -public class OrderProductReqDto { - @NotNull(message = "상품 ID를 입력해주세요.") - private UUID productId; +public record OrderProductReqDto( + @NotNull(message = "상품 ID를 입력해주세요.") + UUID productId, - @NotBlank(message = "카테고리를 입력해주세요.") - private String category; + @NotBlank(message = "카테고리를 입력해주세요.") + String category, - @NotNull(message = "가격을 입력해주세요.") - private Long price; // 클라이언트가 보내면 DB 통신 1회 사라짐 + @NotNull(message = "가격을 입력해주세요.") + Long price, - @NotNull(message = "수량을 입력해주세요.") - private Integer quantity; + @NotNull(message = "수량을 입력해주세요.") + Integer quantity +) { + // 정적 팩토리 메서드 of + public static OrderProductReqDto of(UUID productId, String category, Long price, Integer quantity) { + return new OrderProductReqDto(productId, category, price, quantity); + } + + // DTO로부터 엔티티 생성하는 메서드 toEntity + public OrderProduct toEntity(Order order, Product product) { + return OrderProduct.builder() + .order(order) + .product(product) + .category(category) + .price(price) + .quantity(quantity) + .build(); + } } \ No newline at end of file diff --git a/src/main/java/org/example/gc_coffee/dto/request/OrderReqDto.java b/src/main/java/org/example/gc_coffee/dto/request/OrderReqDto.java index 5f6c5ed..0697eb8 100644 --- a/src/main/java/org/example/gc_coffee/dto/request/OrderReqDto.java +++ b/src/main/java/org/example/gc_coffee/dto/request/OrderReqDto.java @@ -4,28 +4,61 @@ import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.Pattern; -import lombok.Builder; -import lombok.Getter; +import org.example.gc_coffee.dto.common.OrderStatus; +import org.example.gc_coffee.entity.Order; +import org.example.gc_coffee.entity.OrderProduct; import java.util.List; -@Getter -@Builder -public class OrderReqDto { +public record OrderReqDto( + @NotBlank(message = "이메일을 입력해주세요.") + @Pattern( + regexp = "^[0-9a-zA-Z]([-_.]?[0-9a-zA-Z])*@[0-9a-zA-Z]([-_.]?[0-9a-zA-Z])+[.][a-zA-Z]{2,3}$", + message = "이메일 주소를 확인해주세요") + String email, - @NotBlank(message = "이메일을 입력해주세요.") - @Pattern(regexp="^[0-9a-zA-Z]([-_.]?[0-9a-zA-Z])*@[0-9a-zA-Z]([-_.]?[0-9a-zA-Z])+[.][a-zA-Z]{2,3}$", - message="이메일 주소를 확인해주세요") - private String email; + @NotBlank(message = "주소 정보를 입력해주세요.") + String address, - @NotBlank(message = "주소 정보를 입력해주세요.") - private String address; + @NotBlank(message = "우편번호 정보를 입력해주세요.") + String postcode, - @NotBlank(message = "우편번호 정보를 입력해주세요.") - private String postcode; + @NotNull(message = "주문 상품이 없습니다.") + @Valid + List orderProductList +) { + // 정적 팩토리 메서드 of + public static OrderReqDto of(String email, String address, String postcode, List orderProductList) { + return new OrderReqDto(email, address, postcode, orderProductList); + } - @NotNull(message = "주문 상품이 없습니다.") - @Valid - private List orderProductList; + // DTO로부터 Order 엔티티 생성하는 메서드 toEntity + public Order toEntity(List orderProducts) { + // 주문 엔티티 생성 + Order order = Order.builder() + .email(email) + .address(address) + .postcode(postcode) + .orderStatus(OrderStatus.ORDER_PLACED) + .orderProducts(orderProducts) + .build(); -} + // 양방향 연관 관계 설정 + order.addOrderProducts(orderProducts); + + return order; + } + + // DTO로부터 Order 엔티티 생성하는 메서드 toEntity + public Order toEntity() { + // 주문 엔티티 생성 + Order order = Order.builder() + .email(email) + .address(address) + .postcode(postcode) + .orderStatus(OrderStatus.ORDER_PLACED) + .build(); + + return order; + } +} \ No newline at end of file diff --git a/src/main/java/org/example/gc_coffee/dto/request/ProductReqDto.java b/src/main/java/org/example/gc_coffee/dto/request/ProductReqDto.java index 370f51e..9def297 100644 --- a/src/main/java/org/example/gc_coffee/dto/request/ProductReqDto.java +++ b/src/main/java/org/example/gc_coffee/dto/request/ProductReqDto.java @@ -2,20 +2,33 @@ import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; -import lombok.*; +import org.example.gc_coffee.entity.Product; -@Getter -@Builder -public class ProductReqDto { - @NotBlank(message = "제품명을 입력해주세요.") - private String name; +public record ProductReqDto( + @NotBlank(message = "제품명을 입력해주세요.") + String name, - @NotBlank(message = "카테고리를 입력해주세요.") - private String category; + @NotBlank(message = "카테고리를 입력해주세요.") + String category, - @NotNull(message = "가격을 입력해주세요.") - private Long price; + @NotNull(message = "가격을 입력해주세요.") + Long price, - @NotBlank(message = "제품 설명을 입력해주세요.") - private String description; + @NotBlank(message = "제품 설명을 입력해주세요.") + String description +) { + // 정적 팩토리 메서드 of + public static ProductReqDto of(String name, String category, Long price, String description) { + return new ProductReqDto(name, category, price, description); + } + + // DTO로부터 엔티티 생성하는 메서드 toEntity + public Product toEntity() { + return Product.builder() + .name(name) + .category(category) + .price(price) + .description(description) + .build(); + } } \ No newline at end of file diff --git a/src/main/java/org/example/gc_coffee/dto/response/BaseResDto.java b/src/main/java/org/example/gc_coffee/dto/response/BaseResDto.java deleted file mode 100644 index e948039..0000000 --- a/src/main/java/org/example/gc_coffee/dto/response/BaseResDto.java +++ /dev/null @@ -1,16 +0,0 @@ -package org.example.gc_coffee.dto.response; - -import lombok.*; -import lombok.experimental.SuperBuilder; - -import java.time.LocalDateTime; - -@Getter -@ToString -@NoArgsConstructor -@AllArgsConstructor -@SuperBuilder -public abstract class BaseResDto { - private LocalDateTime createdAt; - private LocalDateTime updatedAt; -} diff --git a/src/main/java/org/example/gc_coffee/dto/response/OrderProductResDto.java b/src/main/java/org/example/gc_coffee/dto/response/OrderProductResDto.java index c813b29..a35c755 100644 --- a/src/main/java/org/example/gc_coffee/dto/response/OrderProductResDto.java +++ b/src/main/java/org/example/gc_coffee/dto/response/OrderProductResDto.java @@ -1,20 +1,39 @@ package org.example.gc_coffee.dto.response; -import lombok.*; -import lombok.experimental.SuperBuilder; +import org.example.gc_coffee.entity.Order; +import org.example.gc_coffee.entity.OrderProduct; +import org.example.gc_coffee.entity.Product; +import java.time.LocalDateTime; import java.util.UUID; -@Getter -@ToString -@NoArgsConstructor -@AllArgsConstructor -@SuperBuilder -public class OrderProductResDto extends BaseResDto { - private Long seq; - private UUID orderId; - private UUID productId; - private String category; - private Long price; - private Integer quantity; +public record OrderProductResDto( + Long seq, + UUID orderId, + UUID productId, + String category, + Long price, + Integer quantity, + LocalDateTime createdAt, + LocalDateTime updatedAt +) { + // 정적 팩토리 메서드 of + public static OrderProductResDto of(Long seq, UUID orderId, UUID productId, String category, Long price, Integer quantity, LocalDateTime createdAt, LocalDateTime updatedAt) { + return new OrderProductResDto(seq, orderId, productId, category, price, quantity, createdAt, updatedAt); + } + + // 엔티티로부터 DTO 생성하는 메서드 from + public static OrderProductResDto from(OrderProduct orderProduct) { + return new OrderProductResDto( + orderProduct.getSeq(), + orderProduct.getOrder().getId(), + orderProduct.getProduct().getId(), + orderProduct.getCategory(), + orderProduct.getPrice(), + orderProduct.getQuantity(), + orderProduct.getCreatedAt(), + orderProduct.getUpdatedAt() + ); + } + } \ No newline at end of file diff --git a/src/main/java/org/example/gc_coffee/dto/response/OrderResDto.java b/src/main/java/org/example/gc_coffee/dto/response/OrderResDto.java index e455159..73888f8 100644 --- a/src/main/java/org/example/gc_coffee/dto/response/OrderResDto.java +++ b/src/main/java/org/example/gc_coffee/dto/response/OrderResDto.java @@ -1,21 +1,45 @@ package org.example.gc_coffee.dto.response; -import lombok.*; -import lombok.experimental.SuperBuilder; +import org.example.gc_coffee.dto.common.OrderStatus; +import org.example.gc_coffee.entity.Order; +import org.example.gc_coffee.entity.OrderProduct; -import java.util.UUID; +import java.time.LocalDateTime; import java.util.List; +import java.util.UUID; +import java.util.stream.Collectors; + +public record OrderResDto( + UUID id, + String email, + String address, + String postcode, + OrderStatus orderStatus, + List orderProductList, // 주문 항목 목록 + LocalDateTime createdAt, + LocalDateTime updatedAt +) { + // 정적 팩토리 메서드 of + public static OrderResDto of(UUID id, String email, String address, String postcode, OrderStatus orderStatus, List orderProducts, LocalDateTime createdAt, LocalDateTime updatedAt) { + return new OrderResDto(id, email, address, postcode, orderStatus, orderProducts, createdAt, updatedAt); + } + + // 엔티티로부터 DTO 생성하는 메서드 from + public static OrderResDto from(Order order) { + List orderProductDtos = order.getOrderProducts().stream() + .map(OrderProductResDto::from) // 각 OrderProduct 엔티티를 OrderProductResDto로 변환 + .collect(Collectors.toList()); + + return new OrderResDto( + order.getId(), + order.getEmail(), + order.getAddress(), + order.getPostcode(), + order.getOrderStatus(), + orderProductDtos, + order.getCreatedAt(), + order.getUpdatedAt() + ); + } -@Getter -@ToString -@NoArgsConstructor -@AllArgsConstructor -@SuperBuilder -public class OrderResDto extends BaseResDto { - private UUID id; - private String email; - private String address; - private String postcode; - private String orderStatus; - private List orderProducts; // 주문 항목 목록 } \ No newline at end of file diff --git a/src/main/java/org/example/gc_coffee/dto/response/ProductResDto.java b/src/main/java/org/example/gc_coffee/dto/response/ProductResDto.java index 3bbcf7b..635f9cb 100644 --- a/src/main/java/org/example/gc_coffee/dto/response/ProductResDto.java +++ b/src/main/java/org/example/gc_coffee/dto/response/ProductResDto.java @@ -1,19 +1,33 @@ package org.example.gc_coffee.dto.response; -import lombok.*; -import lombok.experimental.SuperBuilder; - +import org.example.gc_coffee.entity.Product; +import java.time.LocalDateTime; import java.util.UUID; -@Getter -@ToString -@NoArgsConstructor -@AllArgsConstructor -@SuperBuilder -public class ProductResDto extends BaseResDto { - private UUID id; - private String name; - private String category; - private Long price; - private String description; +public record ProductResDto( + UUID id, + String name, + String category, + Long price, + String description, + LocalDateTime createdAt, + LocalDateTime updatedAt +) { + // 정적 팩토리 메서드 of + public static ProductResDto of(UUID id, String name, String category, Long price, String description, LocalDateTime createdAt, LocalDateTime updatedAt) { + return new ProductResDto(id, name, category, price, description, createdAt, updatedAt); + } + + // 엔티티로부터 DTO 생성하는 메서드 from + public static ProductResDto from(Product product) { + return new ProductResDto( + product.getId(), + product.getName(), + product.getCategory(), + product.getPrice(), + product.getDescription(), + product.getCreatedAt(), + product.getUpdatedAt() + ); + } } \ No newline at end of file diff --git a/src/main/java/org/example/gc_coffee/service/OrderServiceImpl.java b/src/main/java/org/example/gc_coffee/service/OrderServiceImpl.java index 71d1c20..62a3c8c 100644 --- a/src/main/java/org/example/gc_coffee/service/OrderServiceImpl.java +++ b/src/main/java/org/example/gc_coffee/service/OrderServiceImpl.java @@ -6,7 +6,6 @@ import org.example.gc_coffee.dto.request.OrderProductReqDto; import org.example.gc_coffee.dto.request.OrderReqDto; import org.example.gc_coffee.dto.response.OrderResDto; -import org.example.gc_coffee.dto.response.OrderProductResDto; import org.example.gc_coffee.entity.Order; import org.example.gc_coffee.entity.OrderProduct; import org.example.gc_coffee.entity.Product; @@ -14,7 +13,6 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.UUID; @@ -27,6 +25,7 @@ public class OrderServiceImpl implements OrderService { private final OrderRepository orderRepository; private final ProductService productService; + private final OrderProductService orderProductService; @Override public List getOrderByEmail(String email) { @@ -35,7 +34,7 @@ public List getOrderByEmail(String email) { List orders = orderRepository.findAllByEmailWithOrderProducts(email); return orders.stream() - .map(OrderServiceImpl::buildOrderDto) + .map(OrderResDto::from) // DTO의 정적 메서드 사용 .toList(); } catch (Exception e) { @@ -50,9 +49,9 @@ public List getAllOrders() { // 페치 조인을 사용하여 모든 Order와 연관된 OrderProduct를 한 번에 가져옴 List orders = orderRepository.findAllWithOrderProducts(); - // Order 엔티티들을 OrderDto로 변환 + // Order 엔티티들을 OrderResDto로 변환 return orders.stream() - .map(OrderServiceImpl::buildOrderDto) + .map(OrderResDto::from) // DTO의 정적 메서드 사용 .toList(); } catch (Exception e) { log.error("Error occurred while fetching all orders", e); @@ -64,39 +63,39 @@ public List getAllOrders() { @Transactional public void registerOrder(OrderReqDto orderReqDto) { try { - Order order = Order.builder() - .id(UUID.randomUUID()) - .email(orderReqDto.getEmail()) - .address(orderReqDto.getAddress()) - .postcode(orderReqDto.getPostcode()) - .orderStatus("REGISTER") // TODO ENUM - .orderProducts(new ArrayList<>()) - .build(); - - List productIds = orderReqDto.getOrderProductList().stream() - .map(OrderProductReqDto::getProductId) + Order order = orderReqDto.toEntity(); + orderRepository.save(order); + + // 상품 ID 목록 추출 + List productIds = orderReqDto.orderProductList().stream() + .map(OrderProductReqDto::productId) .toList(); - Map productMap = productService.getProductByIds(productIds); + // 상품 ID로 Product 엔티티 조회 + List products = productService.getProductByIds(productIds); - orderReqDto.getOrderProductList().forEach(orderProductDto -> { - Product product = productMap.get(orderProductDto.getProductId()); + // Product 엔티티를 Map 형태로 변환하여 매핑 + Map productMap = products.stream() + .collect(Collectors.toMap(Product::getId, product -> product)); - if (product == null) { - throw new EntityNotFoundException("Product not found with ID: " + orderProductDto.getProductId()); - } + // OrderProduct 리스트 생성 + List orderProductEntities = orderReqDto.orderProductList().stream() + .map(orderProductDto -> { + Product product = productMap.get(orderProductDto.productId()); - OrderProduct orderProduct = OrderProduct.builder() - .order(order) - .product(product) - .category(orderProductDto.getCategory()) - .price(orderProductDto.getPrice()) - .quantity(orderProductDto.getQuantity()) - .build(); - order.addOrderProduct(orderProduct); - }); + if (product == null) { + throw new EntityNotFoundException("Product not found with ID: " + orderProductDto.productId()); + } - orderRepository.save(order); + return orderProductDto.toEntity(order, product); // DTO의 toEntity 메서드 사용 + }) + .collect(Collectors.toList()); + + // OrderReqDto의 toEntity 메서드를 사용하여 Order 엔티티 생성 +// Order order = orderReqDto.toEntity(orderProductEntities); // DTO의 toEntity 메서드 사용 + + // 주문 상품 저장 + orderProductService.registerOrderProducts(orderProductEntities); log.info("Order successfully registered with ID: {}", order.getId()); } catch (EntityNotFoundException e) { @@ -107,33 +106,4 @@ public void registerOrder(OrderReqDto orderReqDto) { throw e; } } - - private static OrderResDto buildOrderDto(Order order) { - try { - return OrderResDto.builder() - .id(order.getId()) - .email(order.getEmail()) - .address(order.getAddress()) - .postcode(order.getPostcode()) - .orderStatus(order.getOrderStatus()) - .orderProducts(order.getOrderProducts().stream() - .map(opd -> OrderProductResDto.builder() - .seq(opd.getSeq()) - .orderId(opd.getOrder().getId()) - .productId(opd.getProduct().getId()) - .category(opd.getCategory()) - .price(opd.getPrice()) - .quantity(opd.getQuantity()) - .createdAt(opd.getCreatedAt()) - .updatedAt(opd.getUpdatedAt()) - .build()) - .collect(Collectors.toList())) - .createdAt(order.getCreatedAt()) - .updatedAt(order.getUpdatedAt()) - .build(); - } catch (Exception e) { - log.error("Error occurred while building OrderDto for order ID: {}", order.getId(), e); - throw e; - } - } -} +} \ No newline at end of file diff --git a/src/main/java/org/example/gc_coffee/service/ProductServiceImpl.java b/src/main/java/org/example/gc_coffee/service/ProductServiceImpl.java index 0734c98..9b4a4d3 100644 --- a/src/main/java/org/example/gc_coffee/service/ProductServiceImpl.java +++ b/src/main/java/org/example/gc_coffee/service/ProductServiceImpl.java @@ -11,7 +11,6 @@ import org.springframework.stereotype.Service; import java.util.List; -import java.util.Map; import java.util.UUID; import java.util.stream.Collectors; @@ -28,15 +27,8 @@ public ProductResDto getProductByNames(String name) { Product product = productRepository.findByName(name) .orElseThrow(EntityNotFoundException::new); - return ProductResDto.builder() - .id(product.getId()) - .name(product.getName()) - .category(product.getCategory()) - .price(product.getPrice()) - .description(product.getDescription()) - .createdAt(product.getCreatedAt()) - .updatedAt(product.getUpdatedAt()) - .build(); + // 엔티티에서 DTO로 변환하는 메서드 사용 + return ProductResDto.from(product); } catch (EntityNotFoundException e) { log.error("Product not found with name: {}", name, e); throw e; @@ -51,16 +43,9 @@ public List getAllProducts() { try { List products = productRepository.findAll(); + // 엔티티 리스트를 DTO 리스트로 변환 return products.stream() - .map(product -> ProductResDto.builder() - .id(product.getId()) - .name(product.getName()) - .category(product.getCategory()) - .price(product.getPrice()) - .description(product.getDescription()) - .createdAt(product.getCreatedAt()) - .updatedAt(product.getUpdatedAt()) - .build()) + .map(ProductResDto::from) .collect(Collectors.toList()); } catch (Exception e) { log.error("Error occurred while fetching all products", e); @@ -68,23 +53,17 @@ public List getAllProducts() { } } - // 서비스 클래스 내 메서드 @Override public void registerProduct(ProductReqDto productReqDto) { try { // 이미 동일한 이름의 제품이 존재하는지 확인 - boolean exists = productRepository.existsByName(productReqDto.getName()); + boolean exists = productRepository.existsByName(productReqDto.name()); if (exists) { throw new AlreadyExistsException("Product with this name already exists."); } - Product product = Product.builder() - .id(UUID.randomUUID()) // 새 제품 등록이므로 새로운 UUID 생성 - .name(productReqDto.getName()) - .category(productReqDto.getCategory()) - .price(productReqDto.getPrice()) - .description(productReqDto.getDescription()) - .build(); + // DTO에서 엔티티로 변환하는 메서드 사용 + Product product = productReqDto.toEntity(); productRepository.save(product); log.info("Product registered successfully with ID: {}", product.getId()); @@ -98,11 +77,9 @@ public void registerProduct(ProductReqDto productReqDto) { } @Override - public Map getProductByIds(List productIds) { + public List getProductByIds(List productIds) { try { - List products = productRepository.findAllById(productIds); - return products.stream() - .collect(Collectors.toMap(Product::getId, product -> product)); + return productRepository.findAllById(productIds); } catch (Exception e) { log.error("Error occurred while fetching products by IDs", e); throw e; From c45397964ebbb9ec1d198bab8b769d92c1d18283 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A1=B0=EC=9E=AC=EC=A4=91?= <126754298+m-a-king@users.noreply.github.com> Date: Wed, 11 Sep 2024 16:44:23 +0900 Subject: [PATCH 14/39] =?UTF-8?q?TEST=20=EC=BD=94=EB=93=9C=20=EB=B3=B4?= =?UTF-8?q?=EB=A5=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/OrderServiceImplTest.java | 200 ++++++++--------- .../service/ProductServiceImplTest.java | 202 +++++++++--------- 2 files changed, 201 insertions(+), 201 deletions(-) diff --git a/src/test/java/org/example/gc_coffee/service/OrderServiceImplTest.java b/src/test/java/org/example/gc_coffee/service/OrderServiceImplTest.java index beb7525..25a88db 100644 --- a/src/test/java/org/example/gc_coffee/service/OrderServiceImplTest.java +++ b/src/test/java/org/example/gc_coffee/service/OrderServiceImplTest.java @@ -1,100 +1,100 @@ -package org.example.gc_coffee.service; - -import jakarta.persistence.EntityNotFoundException; -import org.example.gc_coffee.dto.request.OrderReqDto; -import org.example.gc_coffee.dto.response.OrderResDto; -import org.example.gc_coffee.entity.Order; -import org.example.gc_coffee.repository.OrderRepository; -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.Collections; -import java.util.List; -import java.util.UUID; - -import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.*; - -@ExtendWith(MockitoExtension.class) -class OrderServiceImplTest { - - @Mock - private OrderRepository orderRepository; - - @Mock - private ProductService productService; - - @InjectMocks - private OrderServiceImpl orderService; - - @Test - void testGetOrderByEmail_ShouldReturnOrderDto_WhenOrdersExist() { - // Given - String email = "test@example.com"; - Order order = Order.builder() - .id(UUID.randomUUID()) - .email(email) - .address("Test Address") - .postcode("12345") - .orderStatus("PENDING") - .orderProducts(new ArrayList<>()) - .build(); - - when(orderRepository.findAllByEmailWithOrderProducts(email)).thenReturn(List.of(order)); - - // When - List result = orderService.getOrderByEmail(email); - - // Then - assertNotNull(result); - for (OrderResDto orderResDto : result) { - assertEquals(email, orderResDto.getEmail()); - } - verify(orderRepository, times(1)).findAllByEmailWithOrderProducts(email); - } - - @Test - void testRegisterOrder_ShouldThrowException_WhenProductNotFound() { - // Given - OrderReqDto orderReqDto = OrderReqDto.builder() - .email("test@example.com") - .address("Test Address") - .postcode("12345") - .orderProductList(null) - .build(); - - when(productService.getProductByIds(any())).thenReturn(Collections.emptyMap()); - - // When & Then - assertThrows(EntityNotFoundException.class, () -> orderService.registerOrder(orderReqDto)); - verify(orderRepository, never()).save(any(Order.class)); - } - - @Test - void testGetAllOrders_ShouldReturnListOfOrderDtos_WhenOrdersExist() { - // Given - Order order = Order.builder() - .id(UUID.randomUUID()) - .email("test@example.com") - .address("Test Address") - .postcode("12345") - .orderStatus("PENDING") - .orderProducts(new ArrayList<>()) - .build(); - - when(orderRepository.findAllWithOrderProducts()).thenReturn(Collections.singletonList(order)); - - // When - List result = orderService.getAllOrders(); - - // Then - assertNotNull(result); - assertEquals(1, result.size()); - verify(orderRepository, times(1)).findAllWithOrderProducts(); - } -} \ No newline at end of file +//package org.example.gc_coffee.service; +// +//import jakarta.persistence.EntityNotFoundException; +//import org.example.gc_coffee.dto.request.OrderReqDto; +//import org.example.gc_coffee.dto.response.OrderResDto; +//import org.example.gc_coffee.entity.Order; +//import org.example.gc_coffee.repository.OrderRepository; +//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.Collections; +//import java.util.List; +//import java.util.UUID; +// +//import static org.junit.jupiter.api.Assertions.*; +//import static org.mockito.ArgumentMatchers.any; +//import static org.mockito.Mockito.*; +// +//@ExtendWith(MockitoExtension.class) +//class OrderServiceImplTest { +// +// @Mock +// private OrderRepository orderRepository; +// +// @Mock +// private ProductService productService; +// +// @InjectMocks +// private OrderServiceImpl orderService; +// +// @Test +// void testGetOrderByEmail_ShouldReturnOrderDto_WhenOrdersExist() { +// // Given +// String email = "test@example.com"; +// Order order = Order.builder() +// .id(UUID.randomUUID()) +// .email(email) +// .address("Test Address") +// .postcode("12345") +// .orderStatus("PENDING") +// .orderProducts(new ArrayList<>()) +// .build(); +// +// when(orderRepository.findAllByEmailWithOrderProducts(email)).thenReturn(List.of(order)); +// +// // When +// List result = orderService.getOrderByEmail(email); +// +// // Then +// assertNotNull(result); +// for (OrderResDto orderResDto : result) { +// assertEquals(email, orderResDto.getEmail()); +// } +// verify(orderRepository, times(1)).findAllByEmailWithOrderProducts(email); +// } +// +// @Test +// void testRegisterOrder_ShouldThrowException_WhenProductNotFound() { +// // Given +// OrderReqDto orderReqDto = OrderReqDto.builder() +// .email("test@example.com") +// .address("Test Address") +// .postcode("12345") +// .orderProductList(null) +// .build(); +// +// when(productService.getProductByIds(any())).thenReturn(Collections.emptyMap()); +// +// // When & Then +// assertThrows(EntityNotFoundException.class, () -> orderService.registerOrder(orderReqDto)); +// verify(orderRepository, never()).save(any(Order.class)); +// } +// +// @Test +// void testGetAllOrders_ShouldReturnListOfOrderDtos_WhenOrdersExist() { +// // Given +// Order order = Order.builder() +// .id(UUID.randomUUID()) +// .email("test@example.com") +// .address("Test Address") +// .postcode("12345") +// .orderStatus("PENDING") +// .orderProducts(new ArrayList<>()) +// .build(); +// +// when(orderRepository.findAllWithOrderProducts()).thenReturn(Collections.singletonList(order)); +// +// // When +// List result = orderService.getAllOrders(); +// +// // Then +// assertNotNull(result); +// assertEquals(1, result.size()); +// verify(orderRepository, times(1)).findAllWithOrderProducts(); +// } +//} \ No newline at end of file diff --git a/src/test/java/org/example/gc_coffee/service/ProductServiceImplTest.java b/src/test/java/org/example/gc_coffee/service/ProductServiceImplTest.java index 26a4481..276010a 100644 --- a/src/test/java/org/example/gc_coffee/service/ProductServiceImplTest.java +++ b/src/test/java/org/example/gc_coffee/service/ProductServiceImplTest.java @@ -1,119 +1,119 @@ -package org.example.gc_coffee.service; - -import jakarta.persistence.EntityNotFoundException; -import org.example.gc_coffee.dto.response.ProductResDto; -import org.example.gc_coffee.entity.Product; -import org.example.gc_coffee.repository.ProductRepository; -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.Collections; -import java.util.List; -import java.util.Optional; -import java.util.UUID; - -import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.Mockito.*; - -@ExtendWith(MockitoExtension.class) -class ProductServiceImplTest { - - @Mock - private ProductRepository productRepository; - - @InjectMocks - private ProductServiceImpl productService; - - @Test - void testGetProductByNames_ShouldReturnProductDto_WhenProductExists() { - // Given - String productName = "Columbia"; - Product product = Product.builder() - .id(UUID.randomUUID()) - .name(productName) - .category("Coffee Beans") - .price(16000L) - .description("Great coffee") - .build(); - - when(productRepository.findByName(productName)).thenReturn(Optional.of(product)); - - // When - ProductResDto result = productService.getProductByNames(productName); - - // Then - assertNotNull(result); - assertEquals(productName, result.getName()); - verify(productRepository, times(1)).findByName(productName); - } - - @Test - void testGetProductByNames_ShouldThrowException_WhenProductNotFound() { - // Given - String productName = "NonExistentProduct"; - when(productRepository.findByName(productName)).thenReturn(Optional.empty()); - - // When & Then - assertThrows(EntityNotFoundException.class, () -> productService.getProductByNames(productName)); - verify(productRepository, times(1)).findByName(productName); - } - +//package org.example.gc_coffee.service; +// +//import jakarta.persistence.EntityNotFoundException; +//import org.example.gc_coffee.dto.response.ProductResDto; +//import org.example.gc_coffee.entity.Product; +//import org.example.gc_coffee.repository.ProductRepository; +//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.Collections; +//import java.util.List; +//import java.util.Optional; +//import java.util.UUID; +// +//import static org.junit.jupiter.api.Assertions.*; +//import static org.mockito.Mockito.*; +// +//@ExtendWith(MockitoExtension.class) +//class ProductServiceImplTest { +// +// @Mock +// private ProductRepository productRepository; +// +// @InjectMocks +// private ProductServiceImpl productService; +// // @Test -// void testRegisterProduct_ShouldSaveProduct_WhenProductDoesNotExist() { +// void testGetProductByNames_ShouldReturnProductDto_WhenProductExists() { // // Given -// ProductResDto productResDto = ProductResDto.builder() -// .name("Columbia Quindío") +// String productName = "Columbia"; +// Product product = Product.builder() +// .id(UUID.randomUUID()) +// .name(productName) // .category("Coffee Beans") // .price(16000L) -// .description("A unique coffee with a white wine fermentation process.") +// .description("Great coffee") // .build(); -// when(productRepository.existsByName(productResDto.getName())).thenReturn(false); +// +// when(productRepository.findByName(productName)).thenReturn(Optional.of(product)); // // // When -// productService.registerProduct(productResDto); +// ProductResDto result = productService.getProductByNames(productName); // // // Then -// verify(productRepository, times(1)).save(any(Product.class)); +// assertNotNull(result); +// assertEquals(productName, result.getName()); +// verify(productRepository, times(1)).findByName(productName); +// } +// +// @Test +// void testGetProductByNames_ShouldThrowException_WhenProductNotFound() { +// // Given +// String productName = "NonExistentProduct"; +// when(productRepository.findByName(productName)).thenReturn(Optional.empty()); +// +// // When & Then +// assertThrows(EntityNotFoundException.class, () -> productService.getProductByNames(productName)); +// verify(productRepository, times(1)).findByName(productName); // } // +//// @Test +//// void testRegisterProduct_ShouldSaveProduct_WhenProductDoesNotExist() { +//// // Given +//// ProductResDto productResDto = ProductResDto.builder() +//// .name("Columbia Quindío") +//// .category("Coffee Beans") +//// .price(16000L) +//// .description("A unique coffee with a white wine fermentation process.") +//// .build(); +//// when(productRepository.existsByName(productResDto.getName())).thenReturn(false); +//// +//// // When +//// productService.registerProduct(productResDto); +//// +//// // Then +//// verify(productRepository, times(1)).save(any(Product.class)); +//// } +//// +//// @Test +//// void testRegisterProduct_ShouldThrowException_WhenProductAlreadyExists() { +//// // Given +//// ProductResDto productResDto = ProductResDto.builder() +//// .name("Columbia Quindío") +//// .category("Coffee Beans") +//// .price(16000L) +//// .description("A unique coffee with a white wine fermentation process.") +//// .build(); +//// when(productRepository.existsByName(productResDto.getName())).thenReturn(true); +//// +//// // When & Then +//// assertThrows(AlreadyExistsException.class, () -> productService.registerProduct(productResDto)); +//// verify(productRepository, never()).save(any(Product.class)); +//// } +// // @Test -// void testRegisterProduct_ShouldThrowException_WhenProductAlreadyExists() { +// void testGetAllProducts_ShouldReturnListOfProductDtos_WhenProductsExist() { // // Given -// ProductResDto productResDto = ProductResDto.builder() -// .name("Columbia Quindío") +// Product product = Product.builder() +// .id(UUID.randomUUID()) +// .name("Brazil Serra") // .category("Coffee Beans") // .price(16000L) -// .description("A unique coffee with a white wine fermentation process.") +// .description("Great coffee") // .build(); -// when(productRepository.existsByName(productResDto.getName())).thenReturn(true); // -// // When & Then -// assertThrows(AlreadyExistsException.class, () -> productService.registerProduct(productResDto)); -// verify(productRepository, never()).save(any(Product.class)); +// when(productRepository.findAll()).thenReturn(Collections.singletonList(product)); +// +// // When +// List result = productService.getAllProducts(); +// +// // Then +// assertNotNull(result); +// assertEquals(1, result.size()); +// verify(productRepository, times(1)).findAll(); // } - - @Test - void testGetAllProducts_ShouldReturnListOfProductDtos_WhenProductsExist() { - // Given - Product product = Product.builder() - .id(UUID.randomUUID()) - .name("Brazil Serra") - .category("Coffee Beans") - .price(16000L) - .description("Great coffee") - .build(); - - when(productRepository.findAll()).thenReturn(Collections.singletonList(product)); - - // When - List result = productService.getAllProducts(); - - // Then - assertNotNull(result); - assertEquals(1, result.size()); - verify(productRepository, times(1)).findAll(); - } -} \ No newline at end of file +//} \ No newline at end of file From ebd844ec1cca98644206d1e14687517aaa87fb8c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A1=B0=EC=9E=AC=EC=A4=91?= <126754298+m-a-king@users.noreply.github.com> Date: Wed, 11 Sep 2024 16:45:38 +0900 Subject: [PATCH 15/39] =?UTF-8?q?feat:=20=EC=A3=BC=EB=AC=B8=20=EC=83=81?= =?UTF-8?q?=ED=83=9C=20String=20->=20ENUM?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 그 외, JPA 연관관계 편의 메서드 반복형 추가 --- .../example/gc_coffee/dto/common/OrderStatus.java | 12 ++++++++++++ .../java/org/example/gc_coffee/entity/Order.java | 15 +++++++++++++-- 2 files changed, 25 insertions(+), 2 deletions(-) create mode 100644 src/main/java/org/example/gc_coffee/dto/common/OrderStatus.java diff --git a/src/main/java/org/example/gc_coffee/dto/common/OrderStatus.java b/src/main/java/org/example/gc_coffee/dto/common/OrderStatus.java new file mode 100644 index 0000000..51cb9ac --- /dev/null +++ b/src/main/java/org/example/gc_coffee/dto/common/OrderStatus.java @@ -0,0 +1,12 @@ +package org.example.gc_coffee.dto.common; + +public enum OrderStatus { + ORDER_PLACED, // 주문 완료 + PENDING_PAYMENT, // 결제 대기 + PAYMENT_COMPLETED, // 결제 완료 + PREPARING_SHIPMENT, // 상품 준비 중 + SHIPPED, // 배송 중 + DELIVERED, // 배송 완료 + COMPLETED // 주문 완료 + ; +} diff --git a/src/main/java/org/example/gc_coffee/entity/Order.java b/src/main/java/org/example/gc_coffee/entity/Order.java index 44fb4a4..c5384f3 100644 --- a/src/main/java/org/example/gc_coffee/entity/Order.java +++ b/src/main/java/org/example/gc_coffee/entity/Order.java @@ -5,6 +5,8 @@ import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; +import org.example.gc_coffee.dto.common.OrderStatus; import java.util.ArrayList; import java.util.List; @@ -12,7 +14,7 @@ @Entity @Getter -@Builder +@SuperBuilder @NoArgsConstructor @AllArgsConstructor @Table(name = "orders") @@ -31,8 +33,9 @@ public class Order extends BaseEntity { @Column(name = "postcode", nullable = false) private String postcode; + @Enumerated(EnumType.STRING) @Column(name = "order_status", nullable = false) - private String orderStatus; + private OrderStatus orderStatus; @OneToMany (mappedBy = "order", cascade = CascadeType.ALL, orphanRemoval = true) private List orderProducts = new ArrayList<>(); @@ -44,4 +47,12 @@ public void addOrderProduct(OrderProduct orderProduct) { orderProduct.setOrderInternal(this); // 관계 설정을 위한 내부 메서드 호출 } } + + // OrderProduct 리스트를 추가할 때 양방향 관계 설정 + public void addOrderProducts(List orderProductList) { + for (OrderProduct orderProduct : orderProductList) { + addOrderProduct(orderProduct); // 기존 메서드를 재사용하여 처리 + } + } + } \ No newline at end of file From 73e0d473798c582065730e4f885ea7e1767dcae8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A1=B0=EC=9E=AC=EC=A4=91?= <126754298+m-a-king@users.noreply.github.com> Date: Wed, 11 Sep 2024 16:46:38 +0900 Subject: [PATCH 16/39] =?UTF-8?q?fix:=20=EC=A0=84=EC=97=AD=20=EC=98=88?= =?UTF-8?q?=EC=99=B8=20=ED=95=B8=EB=93=A4=EB=9F=AC=20=EB=B2=84=EA=B7=B8=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rest 를 붙이지 않으니 무한 redirection 되는 버그를 해결 --- .../example/gc_coffee/Exception/GlobalExceptionHandler.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/example/gc_coffee/Exception/GlobalExceptionHandler.java b/src/main/java/org/example/gc_coffee/Exception/GlobalExceptionHandler.java index 09bab0d..e176317 100644 --- a/src/main/java/org/example/gc_coffee/Exception/GlobalExceptionHandler.java +++ b/src/main/java/org/example/gc_coffee/Exception/GlobalExceptionHandler.java @@ -3,10 +3,10 @@ import jakarta.persistence.EntityNotFoundException; import org.example.gc_coffee.dto.common.ApiResponseDto; import org.springframework.http.HttpStatus; -import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RestControllerAdvice; -@ControllerAdvice +@RestControllerAdvice public class GlobalExceptionHandler { @ExceptionHandler(EntityNotFoundException.class) From 6967426febf1fe4176f5b52a2327a2a86ae82b0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A1=B0=EC=9E=AC=EC=A4=91?= <126754298+m-a-king@users.noreply.github.com> Date: Wed, 11 Sep 2024 16:47:42 +0900 Subject: [PATCH 17/39] fix: SuperBuilder MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit superBuilder를 사용해서 상속받은 컬럼도 접근 --- src/main/java/org/example/gc_coffee/entity/OrderProduct.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/example/gc_coffee/entity/OrderProduct.java b/src/main/java/org/example/gc_coffee/entity/OrderProduct.java index 9fbbc87..af59821 100644 --- a/src/main/java/org/example/gc_coffee/entity/OrderProduct.java +++ b/src/main/java/org/example/gc_coffee/entity/OrderProduct.java @@ -5,10 +5,11 @@ import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; @Entity @Getter -@Builder +@SuperBuilder @NoArgsConstructor @AllArgsConstructor @Table(name = "order_items") From 6acfb2e32e19d824015b701ed42c192f10625be0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A1=B0=EC=9E=AC=EC=A4=91?= <126754298+m-a-king@users.noreply.github.com> Date: Wed, 11 Sep 2024 16:48:15 +0900 Subject: [PATCH 18/39] =?UTF-8?q?fix:=20=EB=B0=98=ED=99=98=20=ED=83=80?= =?UTF-8?q?=EC=9E=85=20=EC=A7=81=EA=B4=80=EC=A0=81=EC=9D=B4=EA=B2=8C=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/org/example/gc_coffee/service/ProductService.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/org/example/gc_coffee/service/ProductService.java b/src/main/java/org/example/gc_coffee/service/ProductService.java index 265a22b..d04edca 100644 --- a/src/main/java/org/example/gc_coffee/service/ProductService.java +++ b/src/main/java/org/example/gc_coffee/service/ProductService.java @@ -5,7 +5,6 @@ import org.example.gc_coffee.entity.Product; import java.util.List; -import java.util.Map; import java.util.UUID; public interface ProductService { @@ -14,7 +13,7 @@ public interface ProductService { void registerProduct(ProductReqDto productReqDto); - Map getProductByIds(List productIds); + List getProductByIds(List productIds); ProductResDto getProductByNames(String name); } \ No newline at end of file From fd51bce2cdb4db3cbb4ff1fe3e370cf46591b78f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A1=B0=EC=9E=AC=EC=A4=91?= <126754298+m-a-king@users.noreply.github.com> Date: Wed, 11 Sep 2024 16:48:59 +0900 Subject: [PATCH 19/39] =?UTF-8?q?feat:=20=EC=A3=BC=EB=AC=B8=EC=83=81?= =?UTF-8?q?=ED=92=88=EC=84=9C=EB=B9=84=EC=8A=A4=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 주문 등록을 관리하기 위해서 주문상품 서비스가 필요하다고 생각함 --- .../service/OrderProductService.java | 10 ++++++++ .../service/OrderProductServiceImpl.java | 23 +++++++++++++++++++ 2 files changed, 33 insertions(+) create mode 100644 src/main/java/org/example/gc_coffee/service/OrderProductService.java create mode 100644 src/main/java/org/example/gc_coffee/service/OrderProductServiceImpl.java diff --git a/src/main/java/org/example/gc_coffee/service/OrderProductService.java b/src/main/java/org/example/gc_coffee/service/OrderProductService.java new file mode 100644 index 0000000..8fbd1e4 --- /dev/null +++ b/src/main/java/org/example/gc_coffee/service/OrderProductService.java @@ -0,0 +1,10 @@ +package org.example.gc_coffee.service; + +import org.example.gc_coffee.entity.OrderProduct; + +import java.util.List; + +public interface OrderProductService { + + void registerOrderProducts(List orderProducts); +} diff --git a/src/main/java/org/example/gc_coffee/service/OrderProductServiceImpl.java b/src/main/java/org/example/gc_coffee/service/OrderProductServiceImpl.java new file mode 100644 index 0000000..b24fda5 --- /dev/null +++ b/src/main/java/org/example/gc_coffee/service/OrderProductServiceImpl.java @@ -0,0 +1,23 @@ +package org.example.gc_coffee.service; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.example.gc_coffee.entity.OrderProduct; +import org.example.gc_coffee.repository.OrderProductRepository; +import org.springframework.stereotype.Service; + +import java.util.List; + +@Service +@RequiredArgsConstructor +@Slf4j +public class OrderProductServiceImpl implements OrderProductService { + + private final OrderProductRepository orderProductRepository; + + @Override + public void registerOrderProducts(List orderProducts) { + orderProductRepository.saveAll(orderProducts); + + } +} From fdc5a6e0a75fd4889047c27a10bd93442eb4012b Mon Sep 17 00:00:00 2001 From: shmin Date: Wed, 11 Sep 2024 17:30:32 +0900 Subject: [PATCH 20/39] =?UTF-8?q?=EC=B6=9C=EB=A0=A5=20=EB=9D=BC=EC=9D=B4?= =?UTF-8?q?=EB=B8=8C=EB=9F=AC=EB=A6=AC=20=EB=B3=80=EA=B2=BD=20Log4j2=20->?= =?UTF-8?q?=20Slf4j?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../gc_coffee/aspects/ExecutionTimer.java | 40 +++++++++---------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/src/main/java/org/example/gc_coffee/aspects/ExecutionTimer.java b/src/main/java/org/example/gc_coffee/aspects/ExecutionTimer.java index 1a78a0c..42ee808 100644 --- a/src/main/java/org/example/gc_coffee/aspects/ExecutionTimer.java +++ b/src/main/java/org/example/gc_coffee/aspects/ExecutionTimer.java @@ -1,6 +1,6 @@ package org.example.gc_coffee.aspects; -import lombok.extern.log4j.Log4j2; +import lombok.extern.slf4j.Slf4j; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; @@ -9,7 +9,7 @@ import org.springframework.stereotype.Component; import org.springframework.util.StopWatch; -@Log4j2 +@Slf4j @Component @Aspect public class ExecutionTimer { @@ -18,24 +18,24 @@ public class ExecutionTimer { * @Arund 사용 -> 메서드 실행 전, 후로 시간을 공유해야 하기 때문 * * org.example.gc_coffee.controller.*.*(..) -> controller 패키지 내의 모든 클래스 및 함수 실행 시 동작 */ -// @Around("execution(* org.example.gc_coffee.controller.*.*(..))") -// public Object PackageExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable { -// -// StopWatch stopWatch = new StopWatch(); -// -// stopWatch.start(); -// Object result = joinPoint.proceed(); -// stopWatch.stop(); -// -// long totalTimeMillis = stopWatch.getTotalTimeMillis(); -// -// MethodSignature signature = (MethodSignature) joinPoint.getSignature(); -// String methodName = signature.getMethod().getName(); -// -// log.info("실행 메서드: {}, 실행시간 = {}ms", methodName, totalTimeMillis); -// -// return result; -// } + @Around("execution(* org.example.gc_coffee.controller.*.*(..))") + public Object PackageExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable { + + StopWatch stopWatch = new StopWatch(); + + stopWatch.start(); + Object result = joinPoint.proceed(); + stopWatch.stop(); + + long totalTimeMillis = stopWatch.getTotalTimeMillis(); + + MethodSignature signature = (MethodSignature) joinPoint.getSignature(); + String methodName = signature.getMethod().getName(); + + log.info("실행 메서드: {}, 실행시간 = {}ms", methodName, totalTimeMillis); + + return result; + } From 583a6b807d29b07052680df407b0cbfa17070f7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A1=B0=EC=9E=AC=EC=A4=91?= <126754298+m-a-king@users.noreply.github.com> Date: Wed, 11 Sep 2024 17:33:55 +0900 Subject: [PATCH 21/39] refactor: .collect(Collectors.toList()) ---> .toList() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 더 아름답고, 멋진 코드 나는 완성 --- .../java/org/example/gc_coffee/dto/response/OrderResDto.java | 4 +--- .../java/org/example/gc_coffee/service/OrderServiceImpl.java | 2 +- .../org/example/gc_coffee/service/ProductServiceImpl.java | 2 +- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/main/java/org/example/gc_coffee/dto/response/OrderResDto.java b/src/main/java/org/example/gc_coffee/dto/response/OrderResDto.java index 73888f8..027c537 100644 --- a/src/main/java/org/example/gc_coffee/dto/response/OrderResDto.java +++ b/src/main/java/org/example/gc_coffee/dto/response/OrderResDto.java @@ -2,12 +2,10 @@ import org.example.gc_coffee.dto.common.OrderStatus; import org.example.gc_coffee.entity.Order; -import org.example.gc_coffee.entity.OrderProduct; import java.time.LocalDateTime; import java.util.List; import java.util.UUID; -import java.util.stream.Collectors; public record OrderResDto( UUID id, @@ -28,7 +26,7 @@ public static OrderResDto of(UUID id, String email, String address, String postc public static OrderResDto from(Order order) { List orderProductDtos = order.getOrderProducts().stream() .map(OrderProductResDto::from) // 각 OrderProduct 엔티티를 OrderProductResDto로 변환 - .collect(Collectors.toList()); + .toList(); return new OrderResDto( order.getId(), diff --git a/src/main/java/org/example/gc_coffee/service/OrderServiceImpl.java b/src/main/java/org/example/gc_coffee/service/OrderServiceImpl.java index 62a3c8c..326f443 100644 --- a/src/main/java/org/example/gc_coffee/service/OrderServiceImpl.java +++ b/src/main/java/org/example/gc_coffee/service/OrderServiceImpl.java @@ -89,7 +89,7 @@ public void registerOrder(OrderReqDto orderReqDto) { return orderProductDto.toEntity(order, product); // DTO의 toEntity 메서드 사용 }) - .collect(Collectors.toList()); + .toList(); // OrderReqDto의 toEntity 메서드를 사용하여 Order 엔티티 생성 // Order order = orderReqDto.toEntity(orderProductEntities); // DTO의 toEntity 메서드 사용 diff --git a/src/main/java/org/example/gc_coffee/service/ProductServiceImpl.java b/src/main/java/org/example/gc_coffee/service/ProductServiceImpl.java index 9b4a4d3..fdc12c1 100644 --- a/src/main/java/org/example/gc_coffee/service/ProductServiceImpl.java +++ b/src/main/java/org/example/gc_coffee/service/ProductServiceImpl.java @@ -46,7 +46,7 @@ public List getAllProducts() { // 엔티티 리스트를 DTO 리스트로 변환 return products.stream() .map(ProductResDto::from) - .collect(Collectors.toList()); + .toList(); } catch (Exception e) { log.error("Error occurred while fetching all products", e); throw e; From 70aff181639b5f042bd3eb64e9d7bb77ed13f5bc Mon Sep 17 00:00:00 2001 From: eundeang <111877048+eundeang@users.noreply.github.com> Date: Wed, 11 Sep 2024 10:48:55 +0900 Subject: [PATCH 22/39] =?UTF-8?q?refactor:=20=EB=B6=88=ED=95=84=EC=9A=94?= =?UTF-8?q?=ED=95=9C=20import=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/OrderServiceImplTest.java | 212 +++++++++--------- 1 file changed, 112 insertions(+), 100 deletions(-) diff --git a/src/test/java/org/example/gc_coffee/service/OrderServiceImplTest.java b/src/test/java/org/example/gc_coffee/service/OrderServiceImplTest.java index 25a88db..b2ab691 100644 --- a/src/test/java/org/example/gc_coffee/service/OrderServiceImplTest.java +++ b/src/test/java/org/example/gc_coffee/service/OrderServiceImplTest.java @@ -1,100 +1,112 @@ -//package org.example.gc_coffee.service; -// -//import jakarta.persistence.EntityNotFoundException; -//import org.example.gc_coffee.dto.request.OrderReqDto; -//import org.example.gc_coffee.dto.response.OrderResDto; -//import org.example.gc_coffee.entity.Order; -//import org.example.gc_coffee.repository.OrderRepository; -//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.Collections; -//import java.util.List; -//import java.util.UUID; -// -//import static org.junit.jupiter.api.Assertions.*; -//import static org.mockito.ArgumentMatchers.any; -//import static org.mockito.Mockito.*; -// -//@ExtendWith(MockitoExtension.class) -//class OrderServiceImplTest { -// -// @Mock -// private OrderRepository orderRepository; -// -// @Mock -// private ProductService productService; -// -// @InjectMocks -// private OrderServiceImpl orderService; -// -// @Test -// void testGetOrderByEmail_ShouldReturnOrderDto_WhenOrdersExist() { -// // Given -// String email = "test@example.com"; -// Order order = Order.builder() -// .id(UUID.randomUUID()) -// .email(email) -// .address("Test Address") -// .postcode("12345") -// .orderStatus("PENDING") -// .orderProducts(new ArrayList<>()) -// .build(); -// -// when(orderRepository.findAllByEmailWithOrderProducts(email)).thenReturn(List.of(order)); -// -// // When -// List result = orderService.getOrderByEmail(email); -// -// // Then -// assertNotNull(result); -// for (OrderResDto orderResDto : result) { -// assertEquals(email, orderResDto.getEmail()); -// } -// verify(orderRepository, times(1)).findAllByEmailWithOrderProducts(email); -// } -// -// @Test -// void testRegisterOrder_ShouldThrowException_WhenProductNotFound() { -// // Given -// OrderReqDto orderReqDto = OrderReqDto.builder() -// .email("test@example.com") -// .address("Test Address") -// .postcode("12345") -// .orderProductList(null) -// .build(); -// -// when(productService.getProductByIds(any())).thenReturn(Collections.emptyMap()); -// -// // When & Then -// assertThrows(EntityNotFoundException.class, () -> orderService.registerOrder(orderReqDto)); -// verify(orderRepository, never()).save(any(Order.class)); -// } -// -// @Test -// void testGetAllOrders_ShouldReturnListOfOrderDtos_WhenOrdersExist() { -// // Given -// Order order = Order.builder() -// .id(UUID.randomUUID()) -// .email("test@example.com") -// .address("Test Address") -// .postcode("12345") -// .orderStatus("PENDING") -// .orderProducts(new ArrayList<>()) -// .build(); -// -// when(orderRepository.findAllWithOrderProducts()).thenReturn(Collections.singletonList(order)); -// -// // When -// List result = orderService.getAllOrders(); -// -// // Then -// assertNotNull(result); -// assertEquals(1, result.size()); -// verify(orderRepository, times(1)).findAllWithOrderProducts(); -// } -//} \ No newline at end of file +package org.example.gc_coffee.service; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import jakarta.persistence.EntityNotFoundException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.UUID; +import org.example.gc_coffee.dto.OrderDto; +import org.example.gc_coffee.dto.OrderProductDto; +import org.example.gc_coffee.entity.Order; +import org.example.gc_coffee.repository.OrderRepository; +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; + +@ExtendWith(MockitoExtension.class) +class OrderServiceImplTest { + + @Mock + private OrderRepository orderRepository; + + @Mock + private ProductService productService; + + @InjectMocks + private OrderServiceImpl orderService; + + @Test + void testGetOrderByEmail_ShouldReturnOrderDto_WhenOrdersExist() { + // Given + String email = "test@example.com"; + Order order = Order.builder() + .id(UUID.randomUUID()) + .email(email) + .address("Test Address") + .postcode("12345") + .orderStatus("PENDING") + .orderProducts(new ArrayList<>()) + .build(); + + when(orderRepository.findAllByEmailWithOrderProducts(email)).thenReturn(List.of(order)); + + // When + List result = orderService.getOrderByEmail(email); + + // Then + assertNotNull(result); + for (OrderDto orderDto : result) { + assertEquals(email, orderDto.getEmail()); + } + verify(orderRepository, times(1)).findAllByEmailWithOrderProducts(email); + } + + @Test + void testRegisterOrder_ShouldThrowException_WhenProductNotFound() { + // Given + OrderDto orderDto = OrderDto.builder() + .email("test@example.com") + .address("Test Address") + .postcode("12345") + .orderStatus("PENDING") + .orderProducts(Collections.singletonList( + OrderProductDto.builder() + .productId(UUID.randomUUID()) + .category("Coffee") + .price(20000L) + .quantity(2) + .build() + )) + .build(); + + when(productService.getProductByIds(any())).thenReturn(Collections.emptyMap()); + + // When & Then + assertThrows(EntityNotFoundException.class, () -> orderService.registerOrder(orderDto)); + verify(orderRepository, never()).save(any(Order.class)); + } + + @Test + void testGetAllOrders_ShouldReturnListOfOrderDtos_WhenOrdersExist() { + // Given + Order order = Order.builder() + .id(UUID.randomUUID()) + .email("test@example.com") + .address("Test Address") + .postcode("12345") + .orderStatus("PENDING") + .orderProducts(new ArrayList<>()) + .build(); + + when(orderRepository.findAllWithOrderProducts()).thenReturn(Collections.singletonList(order)); + + // When + List result = orderService.getAllOrders(); + + // Then + assertNotNull(result); + assertEquals(1, result.size()); + verify(orderRepository, times(1)).findAllWithOrderProducts(); + } +} \ No newline at end of file From 51f9f77ea0497463bfcedfc5083d303d175bdca3 Mon Sep 17 00:00:00 2001 From: eundeang <111877048+eundeang@users.noreply.github.com> Date: Wed, 11 Sep 2024 16:25:04 +0900 Subject: [PATCH 23/39] =?UTF-8?q?test:=20=EC=A0=95=EA=B7=9C=ED=91=9C?= =?UTF-8?q?=ED=98=84=EC=8B=9D=EC=97=90=20=EB=A7=9E=EB=8A=94=20Email=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=20=ED=81=B4=EB=9E=98=EC=8A=A4=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../example/gc_coffee/dto/EmailGenerator.java | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 src/test/java/org/example/gc_coffee/dto/EmailGenerator.java diff --git a/src/test/java/org/example/gc_coffee/dto/EmailGenerator.java b/src/test/java/org/example/gc_coffee/dto/EmailGenerator.java new file mode 100644 index 0000000..1844589 --- /dev/null +++ b/src/test/java/org/example/gc_coffee/dto/EmailGenerator.java @@ -0,0 +1,32 @@ +package org.example.gc_coffee.dto; + +import java.util.Random; + + +public class EmailGenerator { + + private static final String CHARACTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.-"; + private static final String[] DOMAINS = {"com", "net", "org", "co.kr", "edu", "gov"}; + private static final Random random = new Random(); + + // 이메일을 생성하는 메서드 + public static String generateRandomValidEmail() { + int nameLength = random.nextInt(8) + 3; // 3~10자 + int domainNameLength = random.nextInt(5) + 3; // 3~7자 + String name = generateRandomString(nameLength); + String domainName = generateRandomString(domainNameLength); + String domain = DOMAINS[random.nextInt(DOMAINS.length)]; + + return name + "@" + domainName + "." + domain; + } + + // 지정된 길이의 랜덤 문자열을 생성하는 메서드 + private static String generateRandomString(int length) { + StringBuilder sb = new StringBuilder(length); + for (int i = 0; i < length; i++) { + sb.append(CHARACTERS.charAt(random.nextInt(CHARACTERS.length()))); + } + return sb.toString(); + } + +} From e45a048926e919d2e30e5a827d47a6105a343d46 Mon Sep 17 00:00:00 2001 From: eundeang <111877048+eundeang@users.noreply.github.com> Date: Wed, 11 Sep 2024 17:22:14 +0900 Subject: [PATCH 24/39] =?UTF-8?q?test:=20@DisplayName=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/org/example/gc_coffee/service/OrderServiceImplTest.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/test/java/org/example/gc_coffee/service/OrderServiceImplTest.java b/src/test/java/org/example/gc_coffee/service/OrderServiceImplTest.java index b2ab691..27f2971 100644 --- a/src/test/java/org/example/gc_coffee/service/OrderServiceImplTest.java +++ b/src/test/java/org/example/gc_coffee/service/OrderServiceImplTest.java @@ -25,6 +25,7 @@ import org.mockito.junit.jupiter.MockitoExtension; @ExtendWith(MockitoExtension.class) +@DisplayName("OrderServiceImpl 클래스") class OrderServiceImplTest { @Mock From 2a8ac7710f2fe089dc9bde89aa62e919704e0af4 Mon Sep 17 00:00:00 2001 From: eundeang <111877048+eundeang@users.noreply.github.com> Date: Wed, 11 Sep 2024 17:22:43 +0900 Subject: [PATCH 25/39] =?UTF-8?q?test:=20email=20=EC=83=9D=EC=84=B1=20?= =?UTF-8?q?=EC=BD=94=EB=93=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/org/example/gc_coffee/service/OrderServiceImplTest.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/test/java/org/example/gc_coffee/service/OrderServiceImplTest.java b/src/test/java/org/example/gc_coffee/service/OrderServiceImplTest.java index 27f2971..eed87d9 100644 --- a/src/test/java/org/example/gc_coffee/service/OrderServiceImplTest.java +++ b/src/test/java/org/example/gc_coffee/service/OrderServiceImplTest.java @@ -27,6 +27,7 @@ @ExtendWith(MockitoExtension.class) @DisplayName("OrderServiceImpl 클래스") class OrderServiceImplTest { + String email = EmailGenerator.generateRandomValidEmail(); @Mock private OrderRepository orderRepository; From 2af8e80d89e0f9053a1a31397accc2d8dddf0f26 Mon Sep 17 00:00:00 2001 From: eundeang <111877048+eundeang@users.noreply.github.com> Date: Wed, 11 Sep 2024 17:24:15 +0900 Subject: [PATCH 26/39] =?UTF-8?q?test:=20Describe=20:=20OrderByEmail?= =?UTF-8?q?=EB=A9=94=EC=84=9C=EB=93=9C=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=ED=81=B4=EB=9E=98=EC=8A=A4=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/OrderServiceImplTest.java | 34 +++++++------------ 1 file changed, 12 insertions(+), 22 deletions(-) diff --git a/src/test/java/org/example/gc_coffee/service/OrderServiceImplTest.java b/src/test/java/org/example/gc_coffee/service/OrderServiceImplTest.java index eed87d9..26b7332 100644 --- a/src/test/java/org/example/gc_coffee/service/OrderServiceImplTest.java +++ b/src/test/java/org/example/gc_coffee/service/OrderServiceImplTest.java @@ -38,28 +38,18 @@ class OrderServiceImplTest { @InjectMocks private OrderServiceImpl orderService; - @Test - void testGetOrderByEmail_ShouldReturnOrderDto_WhenOrdersExist() { - // Given - String email = "test@example.com"; - Order order = Order.builder() - .id(UUID.randomUUID()) - .email(email) - .address("Test Address") - .postcode("12345") - .orderStatus("PENDING") - .orderProducts(new ArrayList<>()) - .build(); - - when(orderRepository.findAllByEmailWithOrderProducts(email)).thenReturn(List.of(order)); - - // When - List result = orderService.getOrderByEmail(email); - - // Then - assertNotNull(result); - for (OrderDto orderDto : result) { - assertEquals(email, orderDto.getEmail()); + @Nested + @DisplayName("OrderByEmail 메소드는") + class DescribeOrderByEmail { + + @Nested + @DisplayName("이메일에 해당하는 주문이 없는 경우") + class ContextGetOrderByInvalidEmail { + @Test + @DisplayName("빈 배열을 리턴한다.") + void ItReturnsAnEmptyList() { + Assertions.assertTrue(orderService.getOrderByEmail(email).isEmpty()); + } } verify(orderRepository, times(1)).findAllByEmailWithOrderProducts(email); } From 1ba02060f165d3407cf4002b4fec179cb55f17db Mon Sep 17 00:00:00 2001 From: eundeang <111877048+eundeang@users.noreply.github.com> Date: Wed, 11 Sep 2024 17:26:16 +0900 Subject: [PATCH 27/39] =?UTF-8?q?test:=20Context=20:=20=EC=9D=B4=EB=A9=94?= =?UTF-8?q?=EC=9D=BC=EC=97=90=20=ED=95=B4=EB=8B=B9=ED=95=98=EB=8A=94=20?= =?UTF-8?q?=EC=A3=BC=EB=AC=B8=EC=9D=B4=20=EC=9E=88=EB=8A=94=20=EA=B2=BD?= =?UTF-8?q?=EC=9A=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../gc_coffee/service/OrderServiceImplTest.java | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/test/java/org/example/gc_coffee/service/OrderServiceImplTest.java b/src/test/java/org/example/gc_coffee/service/OrderServiceImplTest.java index 26b7332..452caee 100644 --- a/src/test/java/org/example/gc_coffee/service/OrderServiceImplTest.java +++ b/src/test/java/org/example/gc_coffee/service/OrderServiceImplTest.java @@ -52,6 +52,23 @@ void ItReturnsAnEmptyList() { } } verify(orderRepository, times(1)).findAllByEmailWithOrderProducts(email); + + @Nested + @DisplayName("이메일에 해당하는 주문이 있는 경우") + class ContextGetOrderByValidEmail { + @Test + @DisplayName("해당 이메일이 지정한 배열을 리턴한다.") + void ItReturnsNotEmptyArray() { + orderRepository.save( + Order.builder() + .email(email) + .build() + ); + Assertions.assertEquals(orderRepository.findAllByEmailWithOrderProducts(email), + orderService.getOrderByEmail(email)); + } + } + } } @Test From e679601768721898c6aeb0d793d2089558ab9a3a Mon Sep 17 00:00:00 2001 From: eundeang <111877048+eundeang@users.noreply.github.com> Date: Wed, 11 Sep 2024 17:26:42 +0900 Subject: [PATCH 28/39] =?UTF-8?q?test:=20describe:=20getAllOrders=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/OrderServiceImplTest.java | 30 ++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/src/test/java/org/example/gc_coffee/service/OrderServiceImplTest.java b/src/test/java/org/example/gc_coffee/service/OrderServiceImplTest.java index 452caee..50e5c17 100644 --- a/src/test/java/org/example/gc_coffee/service/OrderServiceImplTest.java +++ b/src/test/java/org/example/gc_coffee/service/OrderServiceImplTest.java @@ -51,7 +51,6 @@ void ItReturnsAnEmptyList() { Assertions.assertTrue(orderService.getOrderByEmail(email).isEmpty()); } } - verify(orderRepository, times(1)).findAllByEmailWithOrderProducts(email); @Nested @DisplayName("이메일에 해당하는 주문이 있는 경우") @@ -69,6 +68,35 @@ void ItReturnsNotEmptyArray() { } } } + + @Nested + @DisplayName("getAllOrders 메소드는") + class DescribeGetAllOrder { + @Nested + @DisplayName("주문이 하나도 없는 경우") + class ContextNoOrder { + @Test + @DisplayName("빈 배열을 리턴한다.") + void ItReturnsAnEmptyList() { + Assertions.assertTrue(orderService.getAllOrders().isEmpty()); + } + } + + @Nested + @DisplayName("이메일에 해당하는 주문이 있는 경우") + class ContextExistOrder { + @Test + @DisplayName("저장된 모든 주문 배열을 리턴한다.") + void ItReturnsNotEmptyArray() { + orderRepository.save( + Order.builder() + .email(email) + .build() + ); + Assertions.assertEquals(orderRepository.findAll(), + orderService.getOrderByEmail(email)); + } + } } @Test From f6be55a1c4d1b2baf5282dfad22666439d55926c Mon Sep 17 00:00:00 2001 From: eundeang <111877048+eundeang@users.noreply.github.com> Date: Wed, 11 Sep 2024 17:26:54 +0900 Subject: [PATCH 29/39] =?UTF-8?q?test:=20describe:=20registerOrder=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/OrderServiceImplTest.java | 37 +++++++------------ 1 file changed, 13 insertions(+), 24 deletions(-) diff --git a/src/test/java/org/example/gc_coffee/service/OrderServiceImplTest.java b/src/test/java/org/example/gc_coffee/service/OrderServiceImplTest.java index 50e5c17..22c835e 100644 --- a/src/test/java/org/example/gc_coffee/service/OrderServiceImplTest.java +++ b/src/test/java/org/example/gc_coffee/service/OrderServiceImplTest.java @@ -99,30 +99,19 @@ void ItReturnsNotEmptyArray() { } } - @Test - void testRegisterOrder_ShouldThrowException_WhenProductNotFound() { - // Given - OrderDto orderDto = OrderDto.builder() - .email("test@example.com") - .address("Test Address") - .postcode("12345") - .orderStatus("PENDING") - .orderProducts(Collections.singletonList( - OrderProductDto.builder() - .productId(UUID.randomUUID()) - .category("Coffee") - .price(20000L) - .quantity(2) - .build() - )) - .build(); - - when(productService.getProductByIds(any())).thenReturn(Collections.emptyMap()); - - // When & Then - assertThrows(EntityNotFoundException.class, () -> orderService.registerOrder(orderDto)); - verify(orderRepository, never()).save(any(Order.class)); - } + @Nested + @DisplayName("registerOrder 메소드는") + class DescribeRegisterOrder { + @Nested + @DisplayName("주문 내역에 물품이 하나도 없을 경우") + class ContextNoItem { + //TODO: DTO 넣기 + @Test + @DisplayName("빈 배열을 리턴한다.") + void ItReturnsAnEmptyList() { + Assertions.assertTrue(orderService.getAllOrders().isEmpty()); + } + } @Test void testGetAllOrders_ShouldReturnListOfOrderDtos_WhenOrdersExist() { From 23d601af1de216bcdf1460eb2dd18025640f975f Mon Sep 17 00:00:00 2001 From: eundeang <111877048+eundeang@users.noreply.github.com> Date: Wed, 11 Sep 2024 17:27:44 +0900 Subject: [PATCH 30/39] test: context: ExistOrder --- .../service/OrderServiceImplTest.java | 27 +++++++++++-------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/src/test/java/org/example/gc_coffee/service/OrderServiceImplTest.java b/src/test/java/org/example/gc_coffee/service/OrderServiceImplTest.java index 22c835e..7830808 100644 --- a/src/test/java/org/example/gc_coffee/service/OrderServiceImplTest.java +++ b/src/test/java/org/example/gc_coffee/service/OrderServiceImplTest.java @@ -113,17 +113,22 @@ void ItReturnsAnEmptyList() { } } - @Test - void testGetAllOrders_ShouldReturnListOfOrderDtos_WhenOrdersExist() { - // Given - Order order = Order.builder() - .id(UUID.randomUUID()) - .email("test@example.com") - .address("Test Address") - .postcode("12345") - .orderStatus("PENDING") - .orderProducts(new ArrayList<>()) - .build(); + @Nested + @DisplayName("이메일에 해당하는 주문이 있는 경우") + class ContextExistOrder { + @Test + @DisplayName("저장된 모든 주문 배열을 리턴한다.") + void ItReturnsNotEmptyArray() { + orderRepository.save( + Order.builder() + .email(email) + .build() + ); + Assertions.assertEquals(orderRepository.findAll(), + orderService.getOrderByEmail(email)); + } + } + } when(orderRepository.findAllWithOrderProducts()).thenReturn(Collections.singletonList(order)); From 4780b9b80ce44eeabc579748f63896619fad6567 Mon Sep 17 00:00:00 2001 From: eundeang <111877048+eundeang@users.noreply.github.com> Date: Wed, 11 Sep 2024 17:28:52 +0900 Subject: [PATCH 31/39] =?UTF-8?q?test:=20=EA=B8=B0=EC=A1=B4=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=EC=BD=94=EB=93=9C=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 우형에서 DCI 사용해서 테스트 코드 작성한다길래 변경했습니당 --- .../service/OrderServiceImplTest.java | 31 +++---------------- 1 file changed, 4 insertions(+), 27 deletions(-) diff --git a/src/test/java/org/example/gc_coffee/service/OrderServiceImplTest.java b/src/test/java/org/example/gc_coffee/service/OrderServiceImplTest.java index 7830808..774d8b7 100644 --- a/src/test/java/org/example/gc_coffee/service/OrderServiceImplTest.java +++ b/src/test/java/org/example/gc_coffee/service/OrderServiceImplTest.java @@ -1,23 +1,11 @@ package org.example.gc_coffee.service; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import jakarta.persistence.EntityNotFoundException; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.UUID; -import org.example.gc_coffee.dto.OrderDto; -import org.example.gc_coffee.dto.OrderProductDto; +import org.example.gc_coffee.dto.EmailGenerator; import org.example.gc_coffee.entity.Order; import org.example.gc_coffee.repository.OrderRepository; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InjectMocks; @@ -129,15 +117,4 @@ void ItReturnsNotEmptyArray() { } } } - - when(orderRepository.findAllWithOrderProducts()).thenReturn(Collections.singletonList(order)); - - // When - List result = orderService.getAllOrders(); - - // Then - assertNotNull(result); - assertEquals(1, result.size()); - verify(orderRepository, times(1)).findAllWithOrderProducts(); - } } \ No newline at end of file From 498120b8e771d5fda571b31f7306564346a7c8f7 Mon Sep 17 00:00:00 2001 From: eundeang <111877048+eundeang@users.noreply.github.com> Date: Wed, 11 Sep 2024 17:29:39 +0900 Subject: [PATCH 32/39] test: validation test - email check --- .../example/gc_coffee/dto/ValidationTest.java | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 src/test/java/org/example/gc_coffee/dto/ValidationTest.java diff --git a/src/test/java/org/example/gc_coffee/dto/ValidationTest.java b/src/test/java/org/example/gc_coffee/dto/ValidationTest.java new file mode 100644 index 0000000..6a88539 --- /dev/null +++ b/src/test/java/org/example/gc_coffee/dto/ValidationTest.java @@ -0,0 +1,22 @@ +package org.example.gc_coffee.dto; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.junit.jupiter.MockitoExtension; + +@ExtendWith(MockitoExtension.class) +@DisplayName("Validation test") +public class ValidationTest { + + @Nested + @DisplayName("EmailGenerator validation test") + class DescribeEmail { + @Test + @DisplayName("사용자가 기입한 이메일이 정규표현식에 맞을 경우") + void ContextInvalidEmail() { + String email = EmailGenerator.generateRandomValidEmail(); + } + } +} From d4a7ac1d377a1768f67c4dcd39e2d3662395bab7 Mon Sep 17 00:00:00 2001 From: eundeang <111877048+eundeang@users.noreply.github.com> Date: Thu, 12 Sep 2024 09:21:21 +0900 Subject: [PATCH 33/39] =?UTF-8?q?test:=20=EC=9D=B4=EB=A9=94=EC=9D=BC?= =?UTF-8?q?=EC=97=90=20=ED=95=B4=EB=8B=B9=ED=95=98=EB=8A=94=20=EC=A3=BC?= =?UTF-8?q?=EB=AC=B8=EC=9D=B4=20=EC=9E=88=EB=8A=94=20=EA=B2=BD=EC=9A=B0?= =?UTF-8?q?=EC=9D=98=20beforeafter=20=EC=84=B8=ED=8C=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/OrderServiceImplTest.java | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/test/java/org/example/gc_coffee/service/OrderServiceImplTest.java b/src/test/java/org/example/gc_coffee/service/OrderServiceImplTest.java index 774d8b7..fb26b64 100644 --- a/src/test/java/org/example/gc_coffee/service/OrderServiceImplTest.java +++ b/src/test/java/org/example/gc_coffee/service/OrderServiceImplTest.java @@ -1,9 +1,13 @@ package org.example.gc_coffee.service; +import static org.example.gc_coffee.dto.common.OrderStatus.ORDER_PLACED; + import org.example.gc_coffee.dto.EmailGenerator; import org.example.gc_coffee.entity.Order; import org.example.gc_coffee.repository.OrderRepository; +import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; @@ -73,6 +77,23 @@ void ItReturnsAnEmptyList() { @Nested @DisplayName("이메일에 해당하는 주문이 있는 경우") class ContextExistOrder { + + @BeforeEach + void saveOrder() { + Order order = Order.builder() + .email(email) + .address("주소") + .postcode("12322") + .orderStatus(ORDER_PLACED) + .build(); + orderRepository.save(order); + } + + @AfterEach + void DeleteAllOrders() { + orderRepository.deleteAll(); + } + @Test @DisplayName("저장된 모든 주문 배열을 리턴한다.") void ItReturnsNotEmptyArray() { From 8a13997575448cfc92091da5bd3b6ee8d2a4d97e Mon Sep 17 00:00:00 2001 From: eundeang <111877048+eundeang@users.noreply.github.com> Date: Thu, 12 Sep 2024 09:22:36 +0900 Subject: [PATCH 34/39] test: test-result --- Test Results - OrderServiceImplTest.html | 697 +++++++++++++++++++++++ 1 file changed, 697 insertions(+) create mode 100644 Test Results - OrderServiceImplTest.html diff --git a/Test Results - OrderServiceImplTest.html b/Test Results - OrderServiceImplTest.html new file mode 100644 index 0000000..1fb6838 --- /dev/null +++ b/Test Results - OrderServiceImplTest.html @@ -0,0 +1,697 @@ + + + + + Test Results — OrderServiceImplTest + + + + + + + + + +
+ +
+
    + "/Users/heoeunjeong/Applications/IntelliJ IDEA Ultimate.app/Contents/jbr/Contents/Home/bin/java" -ea -Didea.test.cyclic.buffer.size=1048576 -javaagent:/Users/heoeunjeong/Applications/IntelliJ IDEA Ultimate.app/Contents/lib/idea_rt.jar=64384:/Users/heoeunjeong/Applications/IntelliJ IDEA Ultimate.app/Contents/bin -Dfile.encoding=UTF-8 -classpath /Users/heoeunjeong/Applications/IntelliJ IDEA Ultimate.app/Contents/lib/idea_rt.jar:/Users/heoeunjeong/Applications/IntelliJ IDEA Ultimate.app/Contents/plugins/junit/lib/junit5-rt.jar:/Users/heoeunjeong/Applications/IntelliJ IDEA Ultimate.app/Contents/plugins/junit/lib/junit-rt.jar:/Users/heoeunjeong/Desktop/NBE1_1_Team10/out/test/classes:/Users/heoeunjeong/Desktop/NBE1_1_Team10/out/production/classes:/Users/heoeunjeong/Desktop/NBE1_1_Team10/out/production/resources:/Users/heoeunjeong/.gradle/caches/modules-2/files-2.1/org.springframework.boot/spring-boot-starter-data-jpa/3.3.3/7eeb176d6130f7aa83405fe2985fe7cadc11ebc5/spring-boot-starter-data-jpa-3.3.3.jar:/Users/heoeunjeong/.gradle/caches/modules-2/files-2.1/org.springframework.boot/spring-boot-starter-jdbc/3.3.3/c97a56c12c79d1ce419a306ddee4ccb89b7d3728/spring-boot-starter-jdbc-3.3.3.jar:/Users/heoeunjeong/.gradle/caches/modules-2/files-2.1/org.springframework.boot/spring-boot-starter-security/3.3.3/80c76e69884e061f0197275005d45dd1648e25c2/spring-boot-starter-security-3.3.3.jar:/Users/heoeunjeong/.gradle/caches/modules-2/files-2.1/org.springframework.boot/spring-boot-starter-validation/3.3.3/9a585e4c45168f6c37812ab47df3abf869c9c289/spring-boot-starter-validation-3.3.3.jar:/Users/heoeunjeong/.gradle/caches/modules-2/files-2.1/org.springframework.boot/spring-boot-starter-web/3.3.3/f19325fefd33dc920c0f68547a798ed731a8c70c/spring-boot-starter-web-3.3.3.jar:/Users/heoeunjeong/.gradle/caches/modules-2/files-2.1/org.springframework.boot/spring-boot-starter-aop/3.3.3/f64c22484c1ab36ae70abc752509ec4c7b1abcfc/spring-boot-starter-aop-3.3.3.jar:/Users/heoeunjeong/.gradle/caches/modules-2/files-2.1/org.springframework.boot/spring-boot-starter-test/3.3.3/6774cadaa893fce1f18ff5e528e17f75d32f6670/spring-boot-starter-test-3.3.3.jar:/Users/heoeunjeong/.gradle/caches/modules-2/files-2.1/org.springframework.security/spring-security-test/6.3.3/c27081b501b4348602741722534a32a56ddfef34/spring-security-test-6.3.3.jar:/Users/heoeunjeong/.gradle/caches/modules-2/files-2.1/org.hibernate.orm/hibernate-core/6.5.2.Final/e9e0cc47f6cd2b2553968aee66bd9e55e7485221/hibernate-core-6.5.2.Final.jar:/Users/heoeunjeong/.gradle/caches/modules-2/files-2.1/org.springframework.data/spring-data-jpa/3.3.3/9b89dbd19eee24c4dc4df12564efc603c614aa91/spring-data-jpa-3.3.3.jar:/Users/heoeunjeong/.gradle/caches/modules-2/files-2.1/org.springframework/spring-aspects/6.1.12/b72435b5813755a894531e2cf1565eff1b313574/spring-aspects-6.1.12.jar:/Users/heoeunjeong/.gradle/caches/modules-2/files-2.1/org.springframework.boot/spring-boot-starter/3.3.3/174d6cb1c59036a01756d6bf4d8945325f94155f/spring-boot-starter-3.3.3.jar:/Users/heoeunjeong/.gradle/caches/modules-2/files-2.1/com.zaxxer/HikariCP/5.1.0/8c96e36c14461fc436bb02b264b96ef3ca5dca8c/HikariCP-5.1.0.jar:/Users/heoeunjeong/.gradle/caches/modules-2/files-2.1/org.springframework/spring-jdbc/6.1.12/feb177a07e109f633c3fb1892d22a2867d0b2284/spring-jdbc-6.1.12.jar:/Users/heoeunjeong/.gradle/caches/modules-2/files-2.1/org.springframework.security/spring-security-config/6.3.3/57b2c01e0a9e12b4418668ebc369e39b648e61bb/spring-security-config-6.3.3.jar:/Users/heoeunjeong/.gradle/caches/modules-2/files-2.1/org.springframework.security/spring-security-web/6.3.3/54455b90899cd803e92b020124e859a859f63ee0/spring-security-web-6.3.3.jar:/Users/heoeunjeong/.gradle/caches/modules-2/files-2.1/org.springframework/spring-aop/6.1.12/5fce5ff02455fad179fc0ea05435dfb79bbeaa66/spring-aop-6.1.12.jar:/Users/heoeunjeong/.gradle/caches/modules-2/files-2.1/org.apache.tomcat.embed/tomcat-embed-el/10.1.28/3220f687c5ffc8650559f08ecac5b149838627b3/tomcat-embed-el-10.1.28.jar:/Users/heoeunjeong/.gradle/caches/modules-2/files-2.1/org.hibernate.validator/hibernate-validator/8.0.1.Final/e49e116b3d3928060599b176b3538bb848718e95/hibernate-validator-8.0.1.Final.jar:/Users/heoeunjeong/.gradle/caches/modules-2/files-2.1/org.springframework.boot/spring-boot-starter-json/3.3.3/3dde3b6089f772a77763020cc97a219307a8f39f/spring-boot-starter-json-3.3.3.jar:/Users/heoeunjeong/.gradle/caches/modules-2/files-2.1/org.springframework/spring-webmvc/6.1.12/86bb0c203d68adb4b2675765f5a372f4c5254b2d/spring-webmvc-6.1.12.jar:/Users/heoeunjeong/.gradle/caches/modules-2/files-2.1/org.springframework.boot/spring-boot-starter-tomcat/3.3.3/8ca660b0ecba2f0ff8ce27603fe89953dc4ec18d/spring-boot-starter-tomcat-3.3.3.jar:/Users/heoeunjeong/.gradle/caches/modules-2/files-2.1/org.springframework/spring-web/6.1.12/b60e69b3ec87f8e001537a0fa7e3e2732dfafa7e/spring-web-6.1.12.jar:/Users/heoeunjeong/.gradle/caches/modules-2/files-2.1/org.aspectj/aspectjweaver/1.9.22.1/bca243d0af0db4758fbae45c5f4995cb5dabb612/aspectjweaver-1.9.22.1.jar:/Users/heoeunjeong/.gradle/caches/modules-2/files-2.1/org.springframework.boot/spring-boot-test-autoconfigure/3.3.3/ebce486202d965dc984ff8013a8f87fdb9b6fe46/spring-boot-test-autoconfigure-3.3.3.jar:/Users/heoeunjeong/.gradle/caches/modules-2/files-2.1/org.springframework.boot/spring-boot-test/3.3.3/42a314ffe171b6fb3932a86a884ef721467dc704/spring-boot-test-3.3.3.jar:/Users/heoeunjeong/.gradle/caches/modules-2/files-2.1/com.jayway.jsonpath/json-path/2.9.0/37fe2217f577b0b68b18e62c4d17a8858ecf9b69/json-path-2.9.0.jar:/Users/heoeunjeong/.gradle/caches/modules-2/files-2.1/jakarta.xml.bind/jakarta.xml.bind-api/4.0.2/6cd5a999b834b63238005b7144136379dc36cad2/jakarta.xml.bind-api-4.0.2.jar:/Users/heoeunjeong/.gradle/caches/modules-2/files-2.1/net.minidev/json-smart/2.5.1/4c11d2808d009132dfbbf947ebf37de6bf266c8e/json-smart-2.5.1.jar:/Users/heoeunjeong/.gradle/caches/modules-2/files-2.1/org.assertj/assertj-core/3.25.3/792b270e73aa1cfc28fa135be0b95e69ea451432/assertj-core-3.25.3.jar:/Users/heoeunjeong/.gradle/caches/modules-2/files-2.1/org.awaitility/awaitility/4.2.2/7336242073ebf83fe034e42b46a403c5501b63c9/awaitility-4.2.2.jar:/Users/heoeunjeong/.gradle/caches/modules-2/files-2.1/org.hamcrest/hamcrest/2.2/1820c0968dba3a11a1b30669bb1f01978a91dedc/hamcrest-2.2.jar:/Users/heoeunjeong/.gradle/caches/modules-2/files-2.1/org.junit.jupiter/junit-jupiter/5.10.3/6686d8fbf251f9bf8ecba413cab57b9e00f9134d/junit-jupiter-5.10.3.jar:/Users/heoeunjeong/.gradle/caches/modules-2/files-2.1/org.mockito/mockito-junit-jupiter/5.11.0/8e658dd339f40305ed4293db25545b5df98b171b/mockito-junit-jupiter-5.11.0.jar:/Users/heoeunjeong/.gradle/caches/modules-2/files-2.1/org.mockito/mockito-core/5.11.0/e4069fa4f4ff2c94322cfec5f2e45341c6c70aff/mockito-core-5.11.0.jar:/Users/heoeunjeong/.gradle/caches/modules-2/files-2.1/org.skyscreamer/jsonassert/1.5.3/aaa43e0823d2a0e106e8754d6a9c4ab24e05e9bc/jsonassert-1.5.3.jar:/Users/heoeunjeong/.gradle/caches/modules-2/files-2.1/org.springframework/spring-test/6.1.12/ea59acc56a32e6a46f66c06e5d4c2b8e8c6a2869/spring-test-6.1.12.jar:/Users/heoeunjeong/.gradle/caches/modules-2/files-2.1/org.springframework/spring-core/6.1.12/5f4162fb645c4f72b57b21d721fce9f26edb9bb9/spring-core-6.1.12.jar:/Users/heoeunjeong/.gradle/caches/modules-2/files-2.1/org.xmlunit/xmlunit-core/2.9.1/e5833662d9a1279a37da3ef6f62a1da29fcd68c4/xmlunit-core-2.9.1.jar:/Users/heoeunjeong/.gradle/caches/modules-2/files-2.1/org.springframework.security/spring-security-core/6.3.3/2bf159e3db212d61408a2f728d6d7252dfaf4710/spring-security-core-6.3.3.jar:/Users/heoeunjeong/.gradle/caches/modules-2/files-2.1/jakarta.persistence/jakarta.persistence-api/3.1.0/66901fa1c373c6aff65c13791cc11da72060a8d6/jakarta.persistence-api-3.1.0.jar:/Users/heoeunjeong/.gradle/caches/modules-2/files-2.1/jakarta.transaction/jakarta.transaction-api/2.0.1/51a520e3fae406abb84e2e1148e6746ce3f80a1a/jakarta.transaction-api-2.0.1.jar:/Users/heoeunjeong/.gradle/caches/modules-2/files-2.1/org.springframework/spring-orm/6.1.12/9df98d9ebdfcf5359dbda945de515d8af2cabe89/spring-orm-6.1.12.jar:/Users/heoeunjeong/.gradle/caches/modules-2/files-2.1/org.springframework/spring-context/6.1.12/e69d476d1334935529a61f403749c6b8593e3272/spring-context-6.1.12.jar:/Users/heoeunjeong/.gradle/caches/modules-2/files-2.1/org.springframework.data/spring-data-commons/3.3.3/89ab77494e1e56b058001354265e381a0a2868e6/spring-data-commons-3.3.3.jar:/Users/heoeunjeong/.gradle/caches/modules-2/files-2.1/org.springframework/spring-tx/6.1.12/c47885e494845584e08407b611031ea2bcef0ef7/spring-tx-6.1.12.jar:/Users/heoeunjeong/.gradle/caches/modules-2/files-2.1/org.springframework/spring-beans/6.1.12/f0344fa934f114a15f02c2b1a199189ec12b7eb5/spring-beans-6.1.12.jar:/Users/heoeunjeong/.gradle/caches/modules-2/files-2.1/org.antlr/antlr4-runtime/4.13.0/5a02e48521624faaf5ff4d99afc88b01686af655/antlr4-runtime-4.13.0.jar:/Users/heoeunjeong/.gradle/caches/modules-2/files-2.1/jakarta.annotation/jakarta.annotation-api/2.1.1/48b9bda22b091b1f48b13af03fe36db3be6e1ae3/jakarta.annotation-api-2.1.1.jar:/Users/heoeunjeong/.gradle/caches/modules-2/files-2.1/org.slf4j/slf4j-api/2.0.16/172931663a09a1fa515567af5fbef00897d3c04/slf4j-api-2.0.16.jar:/Users/heoeunjeong/.gradle/caches/modules-2/files-2.1/org.springframework.boot/spring-boot-autoconfigure/3.3.3/4445f0bbf838c1e3aeb5a83bf2367fbd1013237f/spring-boot-autoconfigure-3.3.3.jar:/Users/heoeunjeong/.gradle/caches/modules-2/files-2.1/org.springframework.boot/spring-boot/3.3.3/f34dba93611823e521800a47043267715184911b/spring-boot-3.3.3.jar:/Users/heoeunjeong/.gradle/caches/modules-2/files-2.1/org.springframework.boot/spring-boot-starter-logging/3.3.3/43d07b2e6bbb628c7fc5df103d35ee2eb091522/spring-boot-starter-logging-3.3.3.jar:/Users/heoeunjeong/.gradle/caches/modules-2/files-2.1/org.yaml/snakeyaml/2.2/3af797a25458550a16bf89acc8e4ab2b7f2bfce0/snakeyaml-2.2.jar:/Users/heoeunjeong/.gradle/caches/modules-2/files-2.1/org.springframework/spring-expression/6.1.12/644bbc2e65eb40feb7284b8570d7a7eb8b1fe8df/spring-expression-6.1.12.jar:/Users/heoeunjeong/.gradle/caches/modules-2/files-2.1/jakarta.validation/jakarta.validation-api/3.0.2/92b6631659ba35ca09e44874d3eb936edfeee532/jakarta.validation-api-3.0.2.jar:/Users/heoeunjeong/.gradle/caches/modules-2/files-2.1/org.jboss.logging/jboss-logging/3.5.3.Final/c88fc1d8a96d4c3491f55d4317458ccad53ca663/jboss-logging-3.5.3.Final.jar:/Users/heoeunjeong/.gradle/caches/modules-2/files-2.1/com.fasterxml/classmate/1.7.0/e98374da1f2143ac8e6e0a95036994bb19137a3/classmate-1.7.0.jar:/Users/heoeunjeong/.gradle/caches/modules-2/files-2.1/com.fasterxml.jackson.datatype/jackson-datatype-jsr310/2.17.2/267b85e9ba2892a37be6d80aa9ca1438a0d8c210/jackson-datatype-jsr310-2.17.2.jar:/Users/heoeunjeong/.gradle/caches/modules-2/files-2.1/com.fasterxml.jackson.module/jackson-module-parameter-names/2.17.2/d27b9f95ccce98984c1ba58d61c5a9c072b1ad95/jackson-module-parameter-names-2.17.2.jar:/Users/heoeunjeong/.gradle/caches/modules-2/files-2.1/com.fasterxml.jackson.datatype/jackson-datatype-jdk8/2.17.2/efd3dd0e1d0db8bc72abbe71c15e697bb83b4b45/jackson-datatype-jdk8-2.17.2.jar:/Users/heoeunjeong/.gradle/caches/modules-2/files-2.1/com.fasterxml.jackson.core/jackson-databind/2.17.2/e6deb029e5901e027c129341fac39e515066b68c/jackson-databind-2.17.2.jar:/Users/heoeunjeong/.gradle/caches/modules-2/files-2.1/org.apache.tomcat.embed/tomcat-embed-websocket/10.1.28/1a5ee88106795215e8a7b6cfea46e57cdfc96430/tomcat-embed-websocket-10.1.28.jar:/Users/heoeunjeong/.gradle/caches/modules-2/files-2.1/org.apache.tomcat.embed/tomcat-embed-core/10.1.28/624f53789b7ba96bc3c8e871fb5eed4cab5a7c89/tomcat-embed-core-10.1.28.jar:/Users/heoeunjeong/.gradle/caches/modules-2/files-2.1/io.micrometer/micrometer-observation/1.13.3/99840eb14ecf95d349f39123c867c2ca33808d/micrometer-observation-1.13.3.jar:/Users/heoeunjeong/.gradle/caches/modules-2/files-2.1/jakarta.activation/jakarta.activation-api/2.1.3/fa165bd70cda600368eee31555222776a46b881f/jakarta.activation-api-2.1.3.jar:/Users/heoeunjeong/.gradle/caches/modules-2/files-2.1/net.minidev/accessors-smart/2.5.1/19b820261eb2e7de7d5bde11d1c06e4501dd7e5f/accessors-smart-2.5.1.jar:/Users/heoeunjeong/.gradle/caches/modules-2/files-2.1/net.bytebuddy/byte-buddy/1.14.19/4c0c637b8f47dc08f89240e6f59900011752c97b/byte-buddy-1.14.19.jar:/Users/heoeunjeong/.gradle/caches/modules-2/files-2.1/org.junit.jupiter/junit-jupiter-params/5.10.3/4852f4e4af9074d9214213b199751f99efeab8b9/junit-jupiter-params-5.10.3.jar:/Users/heoeunjeong/.gradle/caches/modules-2/files-2.1/org.junit.jupiter/junit-jupiter-api/5.10.3/a22aa91d1d6c69b2020a9aeb6d095ea81132bfa5/junit-jupiter-api-5.10.3.jar:/Users/heoeunjeong/.gradle/caches/modules-2/files-2.1/net.bytebuddy/byte-buddy-agent/1.14.19/154da3a65b4f4a909d3e5bdec55d1b2b4cbb6ce1/byte-buddy-agent-1.14.19.jar:/Users/heoeunjeong/.gradle/caches/modules-2/files-2.1/com.vaadin.external.google/android-json/0.0.20131108.vaadin1/fa26d351fe62a6a17f5cda1287c1c6110dec413f/android-json-0.0.20131108.vaadin1.jar:/Users/heoeunjeong/.gradle/caches/modules-2/files-2.1/org.springframework/spring-jcl/6.1.12/f46d6016fd1dd3801a0e6fcd64789ac468254944/spring-jcl-6.1.12.jar:/Users/heoeunjeong/.gradle/caches/modules-2/files-2.1/org.springframework.security/spring-security-crypto/6.3.3/a44e901cd1cfa1d6c20d30b69b83499e12e607a1/spring-security-crypto-6.3.3.jar:/Users/heoeunjeong/.gradle/caches/modules-2/files-2.1/ch.qos.logback/logback-classic/1.5.7/ad4ff8ca015737ade8e8a9de07de565c423e5b7a/logback-classic-1.5.7.jar:/Users/heoeunjeong/.gradle/caches/modules-2/files-2.1/org.apache.logging.log4j/log4j-to-slf4j/2.23.1/425ad1eb8a39904d2830e907a324e956fb456520/log4j-to-slf4j-2.23.1.jar:/Users/heoeunjeong/.gradle/caches/modules-2/files-2.1/org.slf4j/jul-to-slf4j/2.0.16/6d57da3e961daac65bcca0dd3def6cd11e48a24a/jul-to-slf4j-2.0.16.jar:/Users/heoeunjeong/.gradle/caches/modules-2/files-2.1/com.fasterxml.jackson.core/jackson-annotations/2.17.2/147b7b9412ffff24339f8aba080b292448e08698/jackson-annotations-2.17.2.jar:/Users/heoeunjeong/.gradle/caches/modules-2/files-2.1/com.fasterxml.jackson.core/jackson-core/2.17.2/969a35cb35c86512acbadcdbbbfb044c877db814/jackson-core-2.17.2.jar:/Users/heoeunjeong/.gradle/caches/modules-2/files-2.1/io.micrometer/micrometer-commons/1.13.3/47b6b093cd6ba80c9da8d973ea79c7ef69a878d5/micrometer-commons-1.13.3.jar:/Users/heoeunjeong/.gradle/caches/modules-2/files-2.1/org.ow2.asm/asm/9.6/aa205cf0a06dbd8e04ece91c0b37c3f5d567546a/asm-9.6.jar:/Users/heoeunjeong/.gradle/caches/modules-2/files-2.1/org.apiguardian/apiguardian-api/1.1.2/a231e0d844d2721b0fa1b238006d15c6ded6842a/apiguardian-api-1.1.2.jar:/Users/heoeunjeong/.gradle/caches/modules-2/files-2.1/org.junit.platform/junit-platform-commons/1.10.3/a353d42a2f13343a7cb80c5228ae66ff64495481/junit-platform-commons-1.10.3.jar:/Users/heoeunjeong/.gradle/caches/modules-2/files-2.1/org.opentest4j/opentest4j/1.3.0/152ea56b3a72f655d4fd677fc0ef2596c3dd5e6e/opentest4j-1.3.0.jar:/Users/heoeunjeong/.gradle/caches/modules-2/files-2.1/ch.qos.logback/logback-core/1.5.7/ba0d0cbac3f21abd28faed3b4931d5b49cc5887e/logback-core-1.5.7.jar:/Users/heoeunjeong/.gradle/caches/modules-2/files-2.1/org.apache.logging.log4j/log4j-api/2.23.1/9c15c29c526d9c6783049c0a77722693c66706e1/log4j-api-2.23.1.jar:/Users/heoeunjeong/.gradle/caches/modules-2/files-2.1/com.mysql/mysql-connector-j/8.3.0/1cc7fa5d61f4bbc113531a4ba6d85d41cf3d57e1/mysql-connector-j-8.3.0.jar:/Users/heoeunjeong/.gradle/caches/modules-2/files-2.1/org.junit.platform/junit-platform-launcher/1.10.3/2e07e6389624f3e93fb2e87aec2fdc30cc84b069/junit-platform-launcher-1.10.3.jar:/Users/heoeunjeong/.gradle/caches/modules-2/files-2.1/org.junit.platform/junit-platform-engine/1.10.3/365a320c3cfd47f3346625e541e424e35dc75c42/junit-platform-engine-1.10.3.jar:/Users/heoeunjeong/.gradle/caches/modules-2/files-2.1/org.glassfish.jaxb/jaxb-runtime/4.0.5/ca84c2a7169b5293e232b9d00d1e4e36d4c3914a/jaxb-runtime-4.0.5.jar:/Users/heoeunjeong/.gradle/caches/modules-2/files-2.1/org.hibernate.common/hibernate-commons-annotations/6.0.6.Final/77a5f94b56d49508e0ee334751db5b78e5ccd50c/hibernate-commons-annotations-6.0.6.Final.jar:/Users/heoeunjeong/.gradle/caches/modules-2/files-2.1/io.smallrye/jandex/3.1.2/a6c1c89925c7df06242b03dddb353116ceb9584c/jandex-3.1.2.jar:/Users/heoeunjeong/.gradle/caches/modules-2/files-2.1/jakarta.inject/jakarta.inject-api/2.0.1/4c28afe1991a941d7702fe1362c365f0a8641d1e/jakarta.inject-api-2.0.1.jar:/Users/heoeunjeong/.gradle/caches/modules-2/files-2.1/org.junit.jupiter/junit-jupiter-engine/5.10.3/48c14e866bb1a87ca35d24ff068463bb202ada24/junit-jupiter-engine-5.10.3.jar:/Users/heoeunjeong/.gradle/caches/modules-2/files-2.1/org.objenesis/objenesis/3.3/1049c09f1de4331e8193e579448d0916d75b7631/objenesis-3.3.jar:/Users/heoeunjeong/.gradle/caches/modules-2/files-2.1/org.glassfish.jaxb/jaxb-core/4.0.5/7b4b11ea5542eea4ad55e1080b23be436795b3/jaxb-core-4.0.5.jar:/Users/heoeunjeong/.gradle/caches/modules-2/files-2.1/org.eclipse.angus/angus-activation/2.0.2/41f1e0ddd157c856926ed149ab837d110955a9fc/angus-activation-2.0.2.jar:/Users/heoeunjeong/.gradle/caches/modules-2/files-2.1/org.glassfish.jaxb/txw2/4.0.5/f36a4ef12120a9bb06d766d6a0e54b144fd7ed98/txw2-4.0.5.jar:/Users/heoeunjeong/.gradle/caches/modules-2/files-2.1/com.sun.istack/istack-commons-runtime/4.1.2/18ec117c85f3ba0ac65409136afa8e42bc74e739/istack-commons-runtime-4.1.2.jar com.intellij.rt.junit.JUnitStarter -ideVersion5 -junit5 org.example.gc_coffee.service.OrderServiceImplTest +Process finished with exit code 0 + +
  • + +
    780 ms
    +
    registerOrder 메소드는
    +
      +
    • + +
      778 ms
      +
      이메일에 해당하는 주문이 있는 경우
      +
        +
      • + +
        778 ms
        +
        passed저장된 모든 주문 배열을 리턴한다.
        +
      • +
      +
    • +
    • + +
      2 ms
      +
      주문 내역에 물품이 하나도 없을 경우
      +
        +
      • + +
        2 ms
        +
        passed빈 배열을 리턴한다.
        +
      • +
      +
    • +
    +
  • +
  • + +
    4 ms
    +
    getAllOrders 메소드는
    +
      +
    • + +
      3 ms
      +
      이메일에 해당하는 주문이 있는 경우
      +
        +
      • + +
        3 ms
        +
        passed저장된 모든 주문 배열을 리턴한다.
        +
      • +
      +
    • +
    • + +
      1 ms
      +
      주문이 하나도 없는 경우
      +
        +
      • + +
        1 ms
        +
        passed빈 배열을 리턴한다.
        +
      • +
      +
    • +
    +
  • +
  • + +
    2 ms
    +
    OrderByEmail 메소드는
    +
      +
    • + +
      1 ms
      +
      이메일에 해당하는 주문이 있는 경우
      +
        +
      • + +
        1 ms
        +
        passed해당 이메일이 지정한 배열을 리턴한다.
        +
      • +
      +
    • +
    • + +
      1 ms
      +
      이메일에 해당하는 주문이 없는 경우
      +
        +
      • + +
        1 ms
        +
        passed빈 배열을 리턴한다.
        +
      • +
      +
    • +
    +
  • +
+
+
+ + + From cd2ed0c1322bfaa87190a311af976d7216214569 Mon Sep 17 00:00:00 2001 From: eundeang <111877048+eundeang@users.noreply.github.com> Date: Thu, 12 Sep 2024 10:41:09 +0900 Subject: [PATCH 35/39] =?UTF-8?q?test:=20registerOrder=20TC=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/OrderServiceImplTest.java | 83 +++++++++++++++++-- 1 file changed, 75 insertions(+), 8 deletions(-) diff --git a/src/test/java/org/example/gc_coffee/service/OrderServiceImplTest.java b/src/test/java/org/example/gc_coffee/service/OrderServiceImplTest.java index fb26b64..a3ccf95 100644 --- a/src/test/java/org/example/gc_coffee/service/OrderServiceImplTest.java +++ b/src/test/java/org/example/gc_coffee/service/OrderServiceImplTest.java @@ -2,9 +2,18 @@ import static org.example.gc_coffee.dto.common.OrderStatus.ORDER_PLACED; +import jakarta.persistence.EntityNotFoundException; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; +import org.aspectj.lang.annotation.Before; import org.example.gc_coffee.dto.EmailGenerator; +import org.example.gc_coffee.dto.request.OrderProductReqDto; +import org.example.gc_coffee.dto.request.OrderReqDto; +import org.example.gc_coffee.dto.request.ProductReqDto; import org.example.gc_coffee.entity.Order; import org.example.gc_coffee.repository.OrderRepository; +import org.example.gc_coffee.repository.ProductRepository; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; @@ -24,6 +33,9 @@ class OrderServiceImplTest { @Mock private OrderRepository orderRepository; + @Mock + private ProductRepository productRepository; + @Mock private ProductService productService; @@ -114,25 +126,80 @@ class DescribeRegisterOrder { @Nested @DisplayName("주문 내역에 물품이 하나도 없을 경우") class ContextNoItem { - //TODO: DTO 넣기 + OrderReqDto orderReqDto; + @BeforeEach + void makeInvalidRequest() { + OrderProductReqDto orderProductReqDto =OrderProductReqDto.of( + UUID.randomUUID(), + "커피", + 12000L, + 1 + ); + List orderProductReqDtoList = new ArrayList<>(); + orderProductReqDtoList.add(orderProductReqDto); + orderReqDto = OrderReqDto.of( + email, + "주소입니다", + "12321", + orderProductReqDtoList + + ); + } + @AfterEach + void deleteOrder() { + productRepository.deleteAll(); + orderRepository.deleteAll(); + } + @Test - @DisplayName("빈 배열을 리턴한다.") + @DisplayName("EntityNotFoundException을 리턴한다.") void ItReturnsAnEmptyList() { - Assertions.assertTrue(orderService.getAllOrders().isEmpty()); + Assertions.assertThrows(EntityNotFoundException.class, () -> orderService.registerOrder(orderReqDto)); } } @Nested @DisplayName("이메일에 해당하는 주문이 있는 경우") class ContextExistOrder { + + OrderReqDto orderReqDto; + + @BeforeEach + void makeValidRequest() { + ProductReqDto productReqDto = ProductReqDto.of( + "콜롬비아 원두", + "원두", + 10000L, + "참 힘들아여" + ); + productService.registerProduct(productReqDto); + + OrderProductReqDto orderProductReqDto =OrderProductReqDto.of( + UUID.randomUUID(), + "커피", + 12000L, + 1 + ); + List orderProductReqDtoList = new ArrayList<>(); + orderProductReqDtoList.add(orderProductReqDto); + orderReqDto = OrderReqDto.of( + email, + "주소입니다", + "12321", + orderProductReqDtoList + ); + orderService.registerOrder(orderReqDto); + } + + + @AfterEach + void deleteProductAndOrder() { + productRepository.deleteAll(); + orderRepository.deleteAll(); + } @Test @DisplayName("저장된 모든 주문 배열을 리턴한다.") void ItReturnsNotEmptyArray() { - orderRepository.save( - Order.builder() - .email(email) - .build() - ); Assertions.assertEquals(orderRepository.findAll(), orderService.getOrderByEmail(email)); } From dc634811529a2dca6f9ab51e608e04c435e43643 Mon Sep 17 00:00:00 2001 From: eundeang <111877048+eundeang@users.noreply.github.com> Date: Thu, 12 Sep 2024 10:41:55 +0900 Subject: [PATCH 36/39] test: test result modified --- Test Results - OrderServiceImplTest.html | 63 ++++++++++++++---------- 1 file changed, 38 insertions(+), 25 deletions(-) diff --git a/Test Results - OrderServiceImplTest.html b/Test Results - OrderServiceImplTest.html index 1fb6838..2933bf9 100644 --- a/Test Results - OrderServiceImplTest.html +++ b/Test Results - OrderServiceImplTest.html @@ -572,9 +572,9 @@
From 67f23f0efef886603ffd929029a23d5570b37dcf Mon Sep 17 00:00:00 2001 From: eundeang <111877048+eundeang@users.noreply.github.com> Date: Thu, 12 Sep 2024 12:16:18 +0900 Subject: [PATCH 37/39] =?UTF-8?q?fix:=20springboottest=EB=A1=9C=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/OrderServiceImplTest.java | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/src/test/java/org/example/gc_coffee/service/OrderServiceImplTest.java b/src/test/java/org/example/gc_coffee/service/OrderServiceImplTest.java index a3ccf95..b29569a 100644 --- a/src/test/java/org/example/gc_coffee/service/OrderServiceImplTest.java +++ b/src/test/java/org/example/gc_coffee/service/OrderServiceImplTest.java @@ -24,22 +24,28 @@ import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.MockBean; -@ExtendWith(MockitoExtension.class) +@SpringBootTest @DisplayName("OrderServiceImpl 클래스") class OrderServiceImplTest { + private static final Logger log = LoggerFactory.getLogger(OrderServiceImplTest.class); String email = EmailGenerator.generateRandomValidEmail(); - @Mock + @Autowired private OrderRepository orderRepository; - @Mock + @Autowired private ProductRepository productRepository; - @Mock + @Autowired private ProductService productService; - @InjectMocks + @Autowired private OrderServiceImpl orderService; @Nested @@ -109,11 +115,12 @@ void DeleteAllOrders() { @Test @DisplayName("저장된 모든 주문 배열을 리턴한다.") void ItReturnsNotEmptyArray() { - orderRepository.save( + Order order = orderRepository.save( Order.builder() .email(email) .build() ); + System.out.println("order = " + order); Assertions.assertEquals(orderRepository.findAll(), orderService.getOrderByEmail(email)); } From f1bd4ebf13a1b91b2db6479c483a10a1ca289439 Mon Sep 17 00:00:00 2001 From: eundeang <111877048+eundeang@users.noreply.github.com> Date: Thu, 12 Sep 2024 17:47:17 +0800 Subject: [PATCH 38/39] =?UTF-8?q?refactor:=20@Transactional=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=ED=9B=84=20=EC=82=AD=EC=A0=9C=20=EB=A9=94=EC=84=9C?= =?UTF-8?q?=EB=93=9C=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/OrderServiceImplTest.java | 150 ++++++++---------- 1 file changed, 66 insertions(+), 84 deletions(-) diff --git a/src/test/java/org/example/gc_coffee/service/OrderServiceImplTest.java b/src/test/java/org/example/gc_coffee/service/OrderServiceImplTest.java index b29569a..ac5ceff 100644 --- a/src/test/java/org/example/gc_coffee/service/OrderServiceImplTest.java +++ b/src/test/java/org/example/gc_coffee/service/OrderServiceImplTest.java @@ -1,36 +1,29 @@ package org.example.gc_coffee.service; -import static org.example.gc_coffee.dto.common.OrderStatus.ORDER_PLACED; - import jakarta.persistence.EntityNotFoundException; import java.util.ArrayList; import java.util.List; import java.util.UUID; -import org.aspectj.lang.annotation.Before; import org.example.gc_coffee.dto.EmailGenerator; import org.example.gc_coffee.dto.request.OrderProductReqDto; import org.example.gc_coffee.dto.request.OrderReqDto; import org.example.gc_coffee.dto.request.ProductReqDto; -import org.example.gc_coffee.entity.Order; +import org.example.gc_coffee.entity.Product; import org.example.gc_coffee.repository.OrderRepository; import org.example.gc_coffee.repository.ProductRepository; -import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; 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.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.transaction.annotation.Transactional; @SpringBootTest +@Transactional @DisplayName("OrderServiceImpl 클래스") class OrderServiceImplTest { private static final Logger log = LoggerFactory.getLogger(OrderServiceImplTest.class); @@ -52,6 +45,33 @@ class OrderServiceImplTest { @DisplayName("OrderByEmail 메소드는") class DescribeOrderByEmail { + void saveOrder() { + ProductReqDto productReqDto = ProductReqDto.of( + "콜롬비아 원두", + "원두", + 10000L, + "참 힘들아여" + ); + productService.registerProduct(productReqDto); + Product product = productRepository.findByName("콜롬비아 원두").orElseThrow(); + + OrderProductReqDto orderProductReqDto = OrderProductReqDto.of( + product.getId(), + "커피", + 12000L, + 1 + ); + List orderProductReqDtoList = new ArrayList<>(); + orderProductReqDtoList.add(orderProductReqDto); + OrderReqDto orderReqDto = OrderReqDto.of( + email, + "주소입니다", + "12321", + orderProductReqDtoList + ); + orderService.registerOrder(orderReqDto); + } + @Nested @DisplayName("이메일에 해당하는 주문이 없는 경우") class ContextGetOrderByInvalidEmail { @@ -68,13 +88,8 @@ class ContextGetOrderByValidEmail { @Test @DisplayName("해당 이메일이 지정한 배열을 리턴한다.") void ItReturnsNotEmptyArray() { - orderRepository.save( - Order.builder() - .email(email) - .build() - ); - Assertions.assertEquals(orderRepository.findAllByEmailWithOrderProducts(email), - orderService.getOrderByEmail(email)); + saveOrder(); + Assertions.assertNotNull(orderRepository.findAllByEmailWithOrderProducts(email)); } } } @@ -82,6 +97,33 @@ void ItReturnsNotEmptyArray() { @Nested @DisplayName("getAllOrders 메소드는") class DescribeGetAllOrder { + void saveOrder() { + ProductReqDto productReqDto = ProductReqDto.of( + "콜롬비아 원두", + "원두", + 10000L, + "참 힘들아여" + ); + productService.registerProduct(productReqDto); + Product product = productRepository.findByName("콜롬비아 원두").orElseThrow(); + + OrderProductReqDto orderProductReqDto = OrderProductReqDto.of( + product.getId(), + "커피", + 12000L, + 1 + ); + List orderProductReqDtoList = new ArrayList<>(); + orderProductReqDtoList.add(orderProductReqDto); + OrderReqDto orderReqDto = OrderReqDto.of( + email, + "주소입니다", + "12321", + orderProductReqDtoList + ); + orderService.registerOrder(orderReqDto); + } + @Nested @DisplayName("주문이 하나도 없는 경우") class ContextNoOrder { @@ -93,36 +135,13 @@ void ItReturnsAnEmptyList() { } @Nested - @DisplayName("이메일에 해당하는 주문이 있는 경우") + @DisplayName("주문이 있는 경우") class ContextExistOrder { - - @BeforeEach - void saveOrder() { - Order order = Order.builder() - .email(email) - .address("주소") - .postcode("12322") - .orderStatus(ORDER_PLACED) - .build(); - orderRepository.save(order); - } - - @AfterEach - void DeleteAllOrders() { - orderRepository.deleteAll(); - } - @Test @DisplayName("저장된 모든 주문 배열을 리턴한다.") void ItReturnsNotEmptyArray() { - Order order = orderRepository.save( - Order.builder() - .email(email) - .build() - ); - System.out.println("order = " + order); - Assertions.assertEquals(orderRepository.findAll(), - orderService.getOrderByEmail(email)); + saveOrder(); + Assertions.assertNotNull(orderRepository.findAll()); } } } @@ -134,9 +153,10 @@ class DescribeRegisterOrder { @DisplayName("주문 내역에 물품이 하나도 없을 경우") class ContextNoItem { OrderReqDto orderReqDto; + @BeforeEach void makeInvalidRequest() { - OrderProductReqDto orderProductReqDto =OrderProductReqDto.of( + OrderProductReqDto orderProductReqDto = OrderProductReqDto.of( UUID.randomUUID(), "커피", 12000L, @@ -152,11 +172,7 @@ void makeInvalidRequest() { ); } - @AfterEach - void deleteOrder() { - productRepository.deleteAll(); - orderRepository.deleteAll(); - } + @Test @DisplayName("EntityNotFoundException을 리턴한다.") @@ -166,44 +182,10 @@ void ItReturnsAnEmptyList() { } @Nested + @DisplayName("이메일에 해당하는 주문이 있는 경우") class ContextExistOrder { - OrderReqDto orderReqDto; - - @BeforeEach - void makeValidRequest() { - ProductReqDto productReqDto = ProductReqDto.of( - "콜롬비아 원두", - "원두", - 10000L, - "참 힘들아여" - ); - productService.registerProduct(productReqDto); - - OrderProductReqDto orderProductReqDto =OrderProductReqDto.of( - UUID.randomUUID(), - "커피", - 12000L, - 1 - ); - List orderProductReqDtoList = new ArrayList<>(); - orderProductReqDtoList.add(orderProductReqDto); - orderReqDto = OrderReqDto.of( - email, - "주소입니다", - "12321", - orderProductReqDtoList - ); - orderService.registerOrder(orderReqDto); - } - - - @AfterEach - void deleteProductAndOrder() { - productRepository.deleteAll(); - orderRepository.deleteAll(); - } @Test @DisplayName("저장된 모든 주문 배열을 리턴한다.") void ItReturnsNotEmptyArray() { From 74ceacba10ab651131d4ef31853c9e22e911d54f Mon Sep 17 00:00:00 2001 From: eundeang <111877048+eundeang@users.noreply.github.com> Date: Thu, 12 Sep 2024 17:47:46 +0800 Subject: [PATCH 39/39] =?UTF-8?q?test:=20test=20=EB=AA=85=EC=84=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Test Results - OrderServiceImplTest.html | 79 ++++++++++++++---------- 1 file changed, 45 insertions(+), 34 deletions(-) diff --git a/Test Results - OrderServiceImplTest.html b/Test Results - OrderServiceImplTest.html index 2933bf9..32f43f6 100644 --- a/Test Results - OrderServiceImplTest.html +++ b/Test Results - OrderServiceImplTest.html @@ -558,9 +558,6 @@ control: "#treecontrol", animated: "fast", collapsed: true, - toggle: function() { - window.console && console.log("%o was toggled", this); - } }); $("#content").css("padding-top", $("#header").height()); @@ -572,9 +569,9 @@