작성
·
215
·
수정됨
0
package sample.cafekiosk.domain.order;
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.test.context.ActiveProfiles;
import sample.cafekiosk.domain.product.Product;
import sample.cafekiosk.domain.product.ProductRepository;
import sample.cafekiosk.domain.product.ProductSellingStatus;
import sample.cafekiosk.domain.product.ProductType;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;
import static org.assertj.core.groups.Tuple.tuple;
import static sample.cafekiosk.domain.product.ProductSellingStatus.*;
import static sample.cafekiosk.domain.product.ProductType.HANDMADE;
@ActiveProfiles("test")
@DataJpaTest
class OrderRepositoryTest {
@Autowired
private OrderRepository orderRepository;
@Autowired
private ProductRepository productRepository;
@DisplayName("원하는 날짜와 주문 상태로 주문들을 가져온다.")
@Test
void findOrdersBy() {
//given
LocalDateTime registeredDateTime1 = LocalDateTime.of(2024, 3, 2, 12, 0);
LocalDateTime registeredDateTime2 = LocalDateTime.of(2024, 3, 9, 12, 0);
Product product1 = createProduct(SELLING, HANDMADE, "아메리카노", 4000, "001");
Product product2 = createProduct(HOLD, HANDMADE, "카페라떼", 4500, "002");
Product product3 = createProduct(STOP_SELLING, HANDMADE, "팥빙수", 7000, "003");
List<Product> products = List.of(product1, product2, product3);
productRepository.saveAll(products);
Order order1 = createOrder(registeredDateTime1, products);
Order order2 = createOrder(registeredDateTime2, products);
List<Order> orders = List.of(order1, order2);
orderRepository.saveAll(orders);
//when
LocalDate findDate = LocalDate.of(2024, 3, 2);
List<Order> findOrders = orderRepository.findOrdersBy(findDate.atStartOfDay(), findDate.atStartOfDay().plusDays(1), OrderStatus.PAYMENT_COMPLETED);
//then
Assertions.assertThat(findOrders).hasSize(1)
.extracting("registeredDateTime", "orderProducts", "orderStatus")
.containsExactlyInAnyOrder(
tuple(registeredDateTime1, products, OrderStatus.PAYMENT_COMPLETED)
);
}
private Order createOrder(LocalDateTime registeredDateTime1, List<Product> products) {
return Order.builder()
.orderStatus(OrderStatus.PAYMENT_COMPLETED)
.registeredDateTime(registeredDateTime1)
.products(products)
.build();
}
private Product createProduct(ProductSellingStatus sellingStatus, ProductType type, String name, int price, String productNumber) {
return Product.builder()
.productNumber(productNumber)
.type(type)
.sellingStatus(sellingStatus)
.name(name)
.price(price)
.build();
}
}
안녕하세요. 우빈님
OrderRepository의 findOrdersBy() 테스트는 직접 작성하라고 하셔서 테스트를 작성하다가 궁금한 점이 생겨 질문 남깁니다.
첫 번째는 Order의 orderProducts를 테스트할 때, products가 프록시 객체로 넘어와서 테스트하지 못하는 거 같습니다.
현재 코드는 테스트가 실패하는 코드고, extracting에서 "orderProducts"를 제외하면 성공하는 테스트가 됩니다.
이럴 때는 어떻게 해결해야 할지 궁금합니다.
두 번째 질문은 제가 작성한 테스트 코드 구조에서 개선할 사항이 있는지 궁금합니다.
강의 잘 보고 있습니다.
감사합니다.
답변 2
0
안녕하세요, 김도형 님!
맞습니다. 말씀주신대로 객체를 그대로 비교하면 프록시이기 때문에 검증이 실패하는데요.
OrderProduct의 항목을 검증하고 싶다면 OrderProductRepository를 통해 별도로 조회해서 검증하는 방법도 있습니다. ㅎㅎ
한번 적용해보시길 바라요.
감사합니다. 🙂
0
안녕하세요, 인프런 AI 인턴입니다.
우빈님, Order에서 orderProducts를 테스트하는 방법에 대한 질문에 대해 답변드리겠습니다.
첫 번째로, orderProducts
가 프록시 객체로 넘어와서 테스트가 실패하는 경우에는 실제 엔티티가 필요한 테스트 상황이라면, 테스트에 필요한 엔티티를 명시적으로 초기화하는 방법을 사용해 보실 수 있습니다. 예를 들면 Hibernate.initialize() 메소드를 사용하여 프록시 객체를 초기화하거나, 트랜잭션 내에서 엔티티를 접근하여 강제로 로딩을 유도하는 방법들이 있습니다.
두 번째로 테스트 코드 구조의 개선사항과 관련하여, 코드를 잘 작성하셨으나 테스트가 실패하는 상황과 테스트가 의도하는 바를 명확히 하는 것이 중요합니다. 또한, 실패할 가능성이 있는 부분에서는 예외 처리나 조건을 추가해서 테스트의 견고함을 높일 수도 있습니다.
Spring Boot에 대한 테스트와 관련하여 더 자세한 사항은 Spring Boot 공식 문서의 테스트 관련 섹션을 참고하시면 도움이 될 것입니다. 아래 URL을 통해서 해당 문서를 확인해보시기 바랍니다.
Spring Boot Reference Documentation v3.1.5 부분, “18. ‘How-to’ Guides > 18.16. Testing” 섹션:
Spring Boot Reference Documentation - Testing
강의와 함께 실습하시면서 좋은 학습 결과가 있기를 바랍니다. 추가적인 질문이 있으시면 언제든지 문의해 주세요.
답변 감사합니다 !