본문 바로가기
Backend

[실전! 스프링부트와 JPA활용] 주문 기능 테스트 / JUnit5의 assertEquals 사용순서

by 햣둘 2025. 4. 8.

테스트 요구사항

- 상품 주문이 성공해야 한다.

- 상품을 주문할 때 재고수량을 초과하면 안된다.

- 주문 취소가 성공해야 한다.

 

상품 주문 테스트 코드

package jpabook.jpashop.service;

import jakarta.persistence.EntityManager;
import jpabook.jpashop.domain.Address;
import jpabook.jpashop.domain.Member;
import jpabook.jpashop.domain.Order;
import jpabook.jpashop.domain.OrderStatus;
import jpabook.jpashop.domain.item.Book;
import jpabook.jpashop.domain.item.Item;
import jpabook.jpashop.exception.NotEnoughStockException;
import jpabook.jpashop.repository.OrderRepository;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.transaction.annotation.Transactional;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;

@SpringBootTest
@Transactional
class OrderServiceTest {

    @Autowired EntityManager em;
    @Autowired OrderService orderService;
    @Autowired OrderRepository orderRepository;

    @Test
    public void 상품주문() throws Exception {
        //given
        Member member = createMember();
        Book book = createBook("시골 JPA", 10000, 10);
        int orderCount = 2;

        //when
        Long orderId = orderService.order(member.getId(), book.getId(), orderCount);

        //then
        Order getOrder = orderRepository.findOne(orderId);

        assertEquals(OrderStatus.ORDER, getOrder.getStatus(),"상품 주문 시 상태는 ORDER");
        assertEquals(1, getOrder.getOrderItems().size(),"주문한 상품 종류 수가 정확해야 한다.");
        assertEquals(10000*orderCount, getOrder.getTotalPrice(), "주문 가격은 가격*수량 이다.");
        assertEquals(8, book.getStockQuantity(), "주문 수량만큼 재고가 줄어야 한다.");
    }

    @Test
    public void 주문취소() throws Exception {
        //...
    }

    @Test
    public void 상품주문_재고수량초과() throws Exception {
        //...
    }

    private Book createBook(String name, int price, int stockQuantity) {
        Book book = new Book();
        book.setName(name);
        book.setPrice(price);
        book.setStockQuantity(stockQuantity);
        em.persist(book);
        return book;
    }

    private Member createMember() {
        Member member = new Member();
        member.setName("회원1");
        member.setAddress(new Address("서울", "강가", "123-123" ));
        em.persist(member);
        return member;
    }
}

 

! 주의 ! 강의 영상과 다른 점

assertEquals 사용순서

영상에서 사용하는 JUnit4는 메세지, 기대하는 값, 실제 값 순서를 사용한다.

반면에 JUnit5는 기대하는 값, 실제 값, 메세지 순서대로 사용한다.

따라서 다음과 같이 수정해야 한다.

강의 영상 : assertEquals("상품 주문 시 상태는 ORDER", OrderStatus.ORDER, getOrder.getStatus());

수정 내역 : assertEquals(OrderStatus.ORDER, getOrder.getStatus(), "상품 주문 시 상태는 ORDER");

 

! 주의 ! 강의 영상과 다른 점

상품주문_재고수량초과 로직

JUnit5부터 테스트에서 예외를 검증하는 방법이 변경되었다.

강의 영상 : @Test(expected=NotEnoughStockException.class) 사용 -> JUnit4에서 필요

수정 내역 : expected 내역 제거

 

상품주문이 정상 동작하는지 확인하는 테스트다. 

Given 절에서 테스트를 위한 회원과 상품을 만들고, When 절에서 실제 상품을 주문하고, Then 절에서 주문 가격이 올바른지, 주문 후 재고 수량이 정확히 줄었는지 검증한다.

 

재고 수량 초과 테스트

재고 수량을 초과해서 상품을 주문해보자. 

이때는 NotEnoughStockException 예외가 발생해야 한다.

 

재고 수량 초과 테스트 코드

    @Test
    public void 상품주문_재고수량초과() throws Exception {
        //given
        Member member = createMember();
        Item item = createBook("시골 JPA", 10000, 10);

        int orderCount = 11;

        //when & then
        assertThrows(NotEnoughStockException.class, () -> {
                orderService.order(member.getId(), item.getId(), orderCount);
        }, "재고 수량 부족 예외가 발생해야 한다.");
    }

 

! 주의 ! 강의 영상과 다른 점

상품주문_재고수량초과 로직

JUnit5부터 테스트에서 예외를 검증하는 방법이 변경되었다.

강의 영상 : @Test(expected=NotEnoughStockException.class) 사용 -> JUnit4에서 필요

수정 내역 : assertThrows(예외, 람다) 사용, 람다를 실행했을 때 지정한 예외가 발생하지 않으면 테스트가 실패한다.

 

코드를 보면 재고는 10권인데 orderCount=11로 재고보다 1권 더 많은 수량을 주문했다. 주문 초과로 다음 로직에서 예외가 발생한다.

public abstract class Item {
	//...

	public void removeStock(int orderQuantity) {
		int restStock = this.stockQuantity - orderQuantity;
		if (restStock < 0) {
			throw new NotEnoughStockException("need more stock");
		}
		this.stockQuantity = restStock;
	}
}

 

주문 취소 테스트

주문 취소 테스트 코드를 작성하자. 주문을 취소하면 그만큼 재고가 증가해야 한다.

 

주문 취소 테스트 코드

    @Test
    public void 주문취소() throws Exception {
        //given
        Member member = createMember();
        Book item = createBook("시골 JPA", 10000, 10);

        int orderCount = 2;
        Long orderId = orderService.order(member.getId(), item.getId(), orderCount);

        //when
        orderService.cancelOrder(orderId);

        //then
        Order getOrder = orderRepository.findOne(orderId);
        assertEquals(OrderStatus.CANCEL, getOrder.getStatus(),"주문 취소 시 상태는 CANCEL이다.");
        assertEquals(10, item.getStockQuantity(), "주문이 취소된 상품은 그만큼 재고가 증가해야 한다.");
    }

 

! 주의 ! 강의 영상과 다른 점

assertEquals 사용 순서

영상에서 사용하는 JUnit4는 메세지, 기대하는 값, 실제 값 순서를 사용한다.

반면에 JUnit5는 기대하는 값, 실제 값, 메세지 순서를 사용한다.

따라서 다음과 같이 수정해야 한다.

강의 영상 : assertEquals(메세지, 기대값, 실제값);

수정 내역 : assertEquals(기대값, 실제값, 메세지);

 

주문을 취소하려면 먼저 주문을 해야 한다.

Given 절에서 주문하고 When 절에서 해당 주문을 취소했다.

Then 절에서 주문상태가 주문취소 상태인지(Cancel), 취소한 만큼 재고가 증가했는지 검증한다.