• 카테고리

    질문 & 답변
  • 세부 분야

    백엔드

  • 해결 여부

    미해결

Order에서 orderProducts 테스트하는 방법이 궁금합니다.

24.03.09 20:22 작성 24.03.09 20:23 수정 조회수 100

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를 통해 별도로 조회해서 검증하는 방법도 있습니다. ㅎㅎ

한번 적용해보시길 바라요.
감사합니다. 🙂

김도형님의 프로필

김도형

질문자

2024.03.30

답변 감사합니다 !

0

인프런 AI 인턴님의 프로필

인프런 AI 인턴

2024.03.11

안녕하세요, 인프런 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

강의와 함께 실습하시면서 좋은 학습 결과가 있기를 바랍니다. 추가적인 질문이 있으시면 언제든지 문의해 주세요.