인프런 영문 브랜드 로고
인프런 영문 브랜드 로고

인프런 커뮤니티 질문&답변

heyho님의 프로필 이미지
heyho

작성한 질문수

Practical Testing: 실용적인 테스트 가이드

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

작성

·

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

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

heyho님의 프로필 이미지
heyho
질문자

답변 감사합니다 !

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

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

heyho님의 프로필 이미지
heyho

작성한 질문수

질문하기