테스트 요구사항
- 상품 주문이 성공해야 한다.
- 상품을 주문할 때 재고수량을 초과하면 안된다.
- 주문 취소가 성공해야 한다.
상품 주문 테스트 코드
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), 취소한 만큼 재고가 증가했는지 검증한다.
'Backend' 카테고리의 다른 글
[실전! 스프링부트와 JPA활용] 웹계층 개발 - 홈화면과 레이아웃 (0) | 2025.04.10 |
---|---|
[실전! 스프링부트와 JPA활용] 주문검색 기능개발 : JPQL, JPA Criteria, Querydsl (0) | 2025.04.09 |
[실전! 스프링부트와 JPA활용] 주문 서비스 개발 / 도메인 모델 패턴 vs 트랜잭션 스크립트 패턴 (0) | 2025.04.07 |
[실전! 스프링부트와 JPA활용] 주문 레포지토리 개발 (0) | 2025.04.06 |
[실전! 스프링부트와 JPA활용] 주문, 주문상품 엔티티 개발 (0) | 2025.04.06 |