inflearn logo
강의

강의

N
챌린지

챌린지

멘토링

멘토링

N
클립

클립

로드맵

로드맵

지식공유

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

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

272

heyho

작성한 질문수 2

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"를 제외하면 성공하는 테스트가 됩니다.

이럴 때는 어떻게 해결해야 할지 궁금합니다.

 

두 번째 질문은 제가 작성한 테스트 코드 구조에서 개선할 사항이 있는지 궁금합니다.

 

강의 잘 보고 있습니다.

감사합니다.

 

 

spring tdd jpa mockito 소프트웨어-테스트 junit5

답변 2

0

박우빈

안녕하세요, 김도형 님!

맞습니다. 말씀주신대로 객체를 그대로 비교하면 프록시이기 때문에 검증이 실패하는데요.

OrderProduct의 항목을 검증하고 싶다면 OrderProductRepository를 통해 별도로 조회해서 검증하는 방법도 있습니다. ㅎㅎ

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

0

heyho

답변 감사합니다 !

0

인프런 AI 인턴

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

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

private 상수 테스트 관련 질문

0

83

1

void는 어떻게 테스트하나요..? void로 애초에 코딩하면 안되나요??

0

126

2

커버리지는 어떻게 활용하시는지 궁금합니다.

0

161

2

테스트 문서화 질문입니다

0

105

2

단위테스트 질문이 있습니다

0

96

2

컨트롤러는 모킹을 한 이유가 궁금합니다.

0

103

2

ERD 가장자리에 있는 도메인 테스트 질문

0

89

2

DTO 검증 필드에 대한 테스트 코드 작성은 어디까지?

0

135

2

OrderCreateRequest DTO에 대해서 궁금한점

0

102

2

고전파의 테스트 대역 사용 대상, 공유 의존성

0

156

2

계층 관련 질문이 있습니다.

0

139

3

'코틀린'에서는 빌더를 따로 쓰지 않는데, 이 때는 어떻게 test fixture를 만드시는지 궁금합니다

1

124

2

혹시 update 로직은 어떻게 테스트하나요? (@Setter?)

0

134

2

단위테스트와 통합테스트의 경계가 궁금합니다.

0

228

2

Service+Repository 통합테스트 관련 질문입니다.

0

150

2

OrderControllerDocsTest 작성 해봤는데요. 날짜 형식이 이상하게 나와요

0

185

2

test 용 .yml

0

90

2

throws Exception

0

80

2

카페키오스크 클래스 문의 ,,

0

89

2

Rest docs 문서용 테스트코드를 따로 작성해야 되나요?

0

174

2

테스트 코드에서 필요한 생성자

0

138

1

tearDown 순서

0

116

2

@Builder 생성자 private

0

136

2

@DisplayName gradle / intellJ

0

93

2