스프링데이터 + JPA/웹 애플리케이션 개발

18. 주문 기능 테스트

sdafdq 2023. 11. 8. 12:24
@Test
public void 상품주문(){
    Member member = new Member();
    member.setUsername("회원1");
    member.setAddress(new Address("서울", "강가", "123-123"));

    em.persist(member);
    Item book = new Book();
    book.setName("시골 JPA");
    book.setPrice(10000);
    book.setStockQuantity(10);
    em.persist(book);

    int orderCount = 2;
    Long orderId = orderSerivce.order(member.getId(), book.getId(), orderCount);

    Item findBook = itemService.findOne(book.getId());

    Order findOrder = orderRepository.findOne(orderId);
    assertThat(findOrder.getStatus()).isEqualTo(OrderStatus.ORDER);
    assertThat(findOrder.getTotalPrice()).isEqualTo(10000 * orderCount);

    assertThat(book.getStockQuantity()).isEqualTo(8);
}

먼저 멤버 만들고,

등록 후,

item 만들고 가격, 제고 등록 후,

 

주문을 해봄.

그 후 다시 조회해서 찾아온 다음, (주문도)

주문 상태가 바뀌었는지,

총 가격이 주문수량 * 상품주문가격과 맞는지,

또 다시 조회해서 찾아온 아이템의 재고가 남아있어야 할 수량과 맞는지.

 

order()를 하게 되면

public Long order(Long memberId, Long itemId, int count){
    Member member = memberRepository.findOne(memberId);
    Item item = itemRepository.findOne(itemId);

    Delivery delivery =  new Delivery();
    delivery.setAddress(member.getAddress());

    OrderItem orderItem = OrderItem.createOrderItem(item, item.getPrice(), count);

    Order order =  Order.createOrder(member, delivery, orderItem);

    orderRepository.save(order);

    return order.getId();
}

member 찾아오고, item 찾아온 다음,

배송정보 등록하고,

createOrderItem을 하는데

public static OrderItem createOrderItem(Item item, int orderPrice, int count){
    OrderItem orderItem = new OrderItem();
    orderItem.setItem(item);
    orderItem.setOrderPrice(orderPrice);
    orderItem.setCount(count);

    item.removeStock(count);
    return orderItem;
}

새 아이템 생성하고,

원본 아이템을 넣고,

주문가격,

주문 수량 하고

원본 아이템에서 재고를 주문수만큼 줄임.

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

재고 - 주문수량이 0이하면 오류를 내뱉음.

아니면 재고에서 줄여버림.

 

public static Order createOrder(Member member, Delivery delivery, OrderItem... orderItems){
    Order order = new Order();
    order.changeMember(member);
    order.changeDelivery(delivery);
    for (OrderItem orderItem : orderItems) {
        order.addOrderItem(orderItem);
    }
    order.setStatus(OrderStatus.ORDER);
    order.setOrderDate(LocalDateTime.now());
    return order;
}

createOrder는 주문에 대한 set을 다 한 다음,

order()에서 받아서 영속성 컨텍스트에 등록시켜줌. 그럼 나중에 트랜잭션 끝날 때 쿼리 나감.

 

그렇게 끝이고, 나머진 그냥 찾아서 비교.

 

 

 

다음 재고수량 초과

@Test
public void 상품주문_재고수량초과(){
    Member member = createMember();
    em.persist(member);

    Item book = createBook("시골 JPA", 10000, 10);
    em.persist(book);

    int orderCount = 11;
    assertThatThrownBy(()->orderSerivce.order(member.getId(), book.getId(), orderCount))
            .isInstanceOf(NotEnoughStockException.class);
}

저거 위에 member 만드는 과정이랑 Item 만드는 과정 메소드로 만듦.

 

저렇게 수량 10개로 두고,

order 하는데, 그 수량이 재고 추가 시,

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

이 메소드에 의해 오류를 뱉음.(Item)

 

order를 콜백함수로 주고, 에러가 나와야 하며, 그 에러의 instance는 NotEnoughStockException 이어야 함.

 

 

 

 

@Test
public void 주문취소(){
    Member member = createMember();
    em.persist(member);

    Item book = createBook("name", 10000, 10);
    em.persist(book);

    int orderCount = 2;

    Long orderId = orderSerivce.order(member.getId(), book.getId(), orderCount);

    Item findBook = itemService.findOne(book.getId());
    assertThat(findBook.getStockQuantity()).isEqualTo(8);

    orderSerivce.cancelOrder(orderId);

    Order findOrder = orderRepository.findOne(orderId);

    assertThat(findOrder.getStatus()).isEqualTo(OrderStatus.CANCEL);
    assertThat(findBook.getStockQuantity()).isEqualTo(10);
}

 

멤버 등록,

아이템 등록

 

주문한다. 

주문 후 아이템을 찾아와서 

재고 보면 8이어야 한다.

 

그 다음 주문 취소 시,

public void cancelOrder(Long orderId){
    Order order = orderRepository.findOne(orderId);

    order.cancel();
}

이게 호출 되어

 

public void cancel(){
    if(delivery.getStatus() == DeliveryStatus.COMP){
        throw new IllegalStateException("이미 배송완료된 상품은 취소가 불가능합니다.");
    }

    this.setStatus(OrderStatus.CANCEL);
    for (OrderItem orderItem : orderItems) {
        orderItem.cancel();
    }
}

orderState를 CANCEL로 바꾸고,

 

public void cancel(){
    this.getItem().addStock(count);
}

이렇게 OrderItem에서 기존 재고를 주문했던수량만큼 더한다.

 

public void addStock(int quantity){
    this.stockQuantity += quantity;
}

Item의 addStock

 

 

'스프링데이터 + JPA > 웹 애플리케이션 개발' 카테고리의 다른 글

20. 웹 계층 개발  (0) 2023.11.09
19. 주문 검색 기능 개발  (0) 2023.11.09
17. 주문 리포지토리, 서비스  (0) 2023.11.07
16. 주문 도메인 개발  (0) 2023.11.07
15. 상품 개발  (0) 2023.11.07