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

작성자 없음

작성자 정보가 삭제된 글입니다.

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

Business Layer 테스트 (3)

@Transactional 차이로 인해 재고의 quantity 가 감소되지 않는 이유에 대해 질문 드립니다.

작성

·

130

0

안녕하세요, 강사님 테스트에 관심이 생겼고, 강사님 덕분에 테스트에 대해 하나하나 알아가는 재미를 느끼는 중입니다!
좋은 강의 감사드립니다!

 

강의를 진행하던 도중 의문이 있어서 질문 드립니다.

 

문제 상황입니다.


stock.deductQuantity(quantity) 부분에서 stock 의 this.quantity 가 파라미터로 들어온 quantity 만큼 갯수가 감소되는 것을 확인하였습니다. (아래 사진에 빨간줄로 밑줄 그었습니다)

image.pngimage.png

 

그러나, 테스트의 결과는 실패로 떴습니다.

그 이유는 감소된 재고의 수량(Stock 의 quantity)이 아래 사진처럼 테스트에 반영되지 않았습니다.

image.png

해당 테스트 코드입니다. 강사님의 테스트 코드와 일치하게 짰습니다.

@DisplayName("재고와 관련된 상품이 포함되어 있는 주문번호 리스트를 받아 주문을 생성한다.")
    @Test
    void createOrderWithStock() {
        // given
        Product product1 = createProduct(BOTTLE, "001", 1000);
        Product product2 = createProduct(BAKERY, "002", 3000);
        Product product3 = createProduct(HANDMADE, "003", 5000);
        productRepository.saveAll(List.of(product1, product2, product3));

        Stock stock1 = Stock.create("001", 2);
        Stock stock2 = Stock.create("002", 2);
        stockRepository.saveAll(List.of(stock1, stock2));

        OrderAddRequest request = OrderAddRequest.builder()
                .productNumbers(List.of("001", "001", "003", "002"))
                .build();
        LocalDateTime registeredDateTime = LocalDateTime.now();

        // when
        OrderResponse orderResponse = orderService.createOrder(request, registeredDateTime);

        // then
        assertThat(orderResponse.getId()).isNotNull();
        assertThat(orderResponse)
                .extracting("registeredDateTime", "totalPrice")
                .contains(registeredDateTime, 10000);
        assertThat(orderResponse.getProducts()).hasSize(4)
                .extracting("productNumber", "price")
                .containsExactlyInAnyOrder(
                        tuple("001", 1000),
                        tuple("001", 1000),
                        tuple("002", 3000),
                        tuple("003", 5000)
                );

        List<Stock> stocks = stockRepository.findAll();
        assertThat(stocks).hasSize(2)
                .extracting("productNumber", "quantity")
                .containsExactlyInAnyOrder(
                        tuple("001", 0),
                        tuple("002", 1)
                );
    } 

 

왜 테스트가 실패하는지 한참 헤매다가 OrderService 에 @Transactional 을 추가하였더니 Stock의 감소된 quantity 가 테스트에 반영이 되었고, 테스트가 성공하게 되었습니다.

// OrderService 중 일부 발췌
@Transactional
@RequiredArgsConstructor
@Service
public class OrderService {

    private final OrderRepository orderRepository;
    private final ProductRepository productRepository;
    private final StockRepository stockRepository;

 

저의 얕은 지식으로는 @Transactional 이 왜 테스트에 영향을 주게 되었는지 이해가 도통되지 않아 강사님께 질문을 드립니다

 

답변 2

0

박우빈님의 프로필 이미지
박우빈
지식공유자

안녕하세요!

해당 현상은 테스트 코드와는 조금 무관한데요 ㅎㅎ
강의 중에도 언급하지만, JPA의 변경 감지 기능에 대해서 학습해보시면 좋을 것 같습니다.
JPA의 변경 감지를 통해 update 쿼리가 생성되는 작업은 트랜잭션 범위 내에서 이루어집니다.

감사합니다 🙂

0

안녕하세요, 인프런 AI 인턴입니다.

종혁님의 질문은 @Transactional 어노테이션의 부재로 인해 재고 수량 감소가 테스트에 반영되지 않는 원인에 관한 것으로 보입니다. 이와 관련하여, @Transactional을 붙였을 때만 Stock 감소 검증에 성공합니다라는 질문에 대한 답을 찾을 수 있을 것 같습니다.

해당 답변 URL은 여기에서 확인하실 수 있습니다. 질문에 제시된 상황과 유사하게, @Transactional을 사용하거나 사용하지 않음에 따라 stock의 quantity 감소를 검증하는 테스트에서 차이가 발생할 수 있음을 논의하고 있습니다. 질문자는 stock의 quantity 감소 로직에 @Transactional 어노테이션을 추가한 후 테스트가 성공했다고 언급하는데, 이는 stock 상태의 변경이 정상적으로 데이터베이스에 반영되어 테스트 내에서 검증될 수 있음을 의미합니다.

요약:

  • @Transactional 어노테이션은 테스트 내에서 데이터베이스 상태의 변경을 영속화하기 위해 필요합니다.
  • 이 어노테이션은 테스트가 실행되는 동안 일어나는 변화(예: stock quantity의 감소)를 데이터베이스에 커밋하여 영속적인 상태 변화를 보장합니다. 이로 인해 해당 변경사항을 다시 조회하거나 검증할 때 올바르게 반영됩니다.
  • 어노테이션을 추가하지 않는 경우, 테스트 종료 시 모든 변경사항이 롤백되어 테스트를 올바르게 검증할 수 없습니다.

저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다.
현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏
추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.

작성자 없음

작성자 정보가 삭제된 글입니다.

질문하기