스프링 부트와 JPA 활용1 - 주문 도메인 개발 3

📌 스프링 부트와 JPA 활용1 - 주문 도메인 개발 3

인프런 - 스프링 부트와 JPA 활용1 by 김영한 을 기반으로 작성된 글입니다.
실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발


주문 도메인 개발 목차

1. 주문, 주문상품 엔티티 개발

2. 주문 리포지토리 개발

3. 주문 서비스 개발

4. 주문 기능 테스트

5. 주문 검색 기능 개발


주문 기능 테스트 (OrderServiceTest.java)

  • 상품 주문이 성공해야 한다.
  • 상품을 주문할 때 재고 수량을 초과하면 안된다.
  • 주문 취소가 성공해야 한다.

1) 상품 주문 테스트

💻 코드 1

package jpabook.jpashop.service;
(생략)

import static org.junit.Assert.assertEquals;
import javax.persistence.EntityManager;

	@RunWith(SpringRunner.class)
    @SpringBootTest
    @Transactional
    public class OrderServiceTest {

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

        @Test
        public void 상품주문() throws Exception{
            //given
            Member member = new Member();
            member.setName("회원1");
            member.setAddress(new Address("서울","강가","123-123"));
            em.persist(member);

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

            int orderCount = 2;

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

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

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

📍 설명 1

1) 기술

  • @RunWith(SpringRunner.class) : JUnit 실행시 SpringRunner.class 라는 확장 클래스 실행
  • @SpringBootTest : 스프링 컨테이너 안에서 테스트 (없으면 @Autowired 실패)
  • @Transactional : 테스트 케이스에서 사용 될 때 기본적으로 Rollback

2) 기능
상품 주문이 정상 동작 하는지 확인하는 테스트

  • given 절 : 테스트를 위한 회원과 상품 입력
  • when 절 : 실제 상품 주문
  • then 절 : 주문 상태, 주문 상품 종류 수, 주문 가격, 주문 후 재고 수량 올바른지 확인
  • jUnit 메서드
    assertEquals(a,b) : 객체 a와 b의 값이 일치하는 지 확인

테스트 실패 경우 확인 해보기

  1. 테스트 통과
    책 가격 : 10,000
    책 수량 : 2
    결과 : 20,000

  2. 테스트 실패
    책 가격 : 1,000
    책 수량 : 2
    결과 : 2,000

❗ 테스트 값 비교 할 때 주문 가격이 실제 주문 가격과 일치 하지 않기에 테스트 실패
10000 * orderCount ≠ getOrder.getTotalPrice()

이런 식으로 제대로 맞게 동작 되는지 확인해 볼 수 있다.

성공!


3) 메서드 추출 기법 ( 리팩토링 ) - 단축키 Ctrl + Alt + B
코드가 길거나 중복돼 사용되는 코드의 경우 메서드로 추출 해서 사용하는 것이 좋다
코드 명료성이 향상 되고 메서드 재사용성과 가독성이 좋다.

주문 생성하는 코드를 상품 주문, 상품 초과 주문, 상품 취소 테스트에서
모두 사용하기 때문에 메서드의 재사용성을 높이기 위해서 메서드를 추출해서 사용해주었다.

//given
Member member = new Member();
member.setName("회원1");
member.setAddress(new Address("서울","강가","123-123"));
em.persist(member);
            
Book book = new Book();
book.setName("시골 JPA");
book.setPrice(10000);
book.setStockQuantity(10);
em.persist(book);

메서드 이름은 메서드를 직관적으로 나타내는 이름으로 생성한다.

//given
{
	//... 
	Member member = createMember();

	Book book = createBook("시골 JPA", 10000, 10);
}   

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

	return member;
}

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;
	// ctrl+alt+p 단축키로 파라미터 꺼낼수 있음
        
    }

2) 상품 초과 주문 테스트

💻 코드 2

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

        //재고는 10개, 주문 수량은 11개면 exception 발생
        int orderCount = 11;

        //when
        orderService.order(member.getId(), item.getId(), orderCount);

        //Then
        fail("재고 수량 부족 예외가 발생해야한다.");

    }

📍 설명 2

1) 기능

  • given 절 : 주문 생성, 재고보다 많은 수량 주문
  • when 절 : 주문
  • then 절 : 재고는 10개, 주문 수량은 11개면 exception 발생

👉 상품 주문 재고 수량에 따른 결과
1) 재고 수량 10개, 주문 수량 10개 일 때


  • JUnit의 Assert fail() 메소드
    실제 예외가 발생했는지 확인하거나 개발 중에 테스트를 실패하게 만들고 싶을 때 사용
//Then
fail("재고 수량 부족 예외가 발생해야한다.");

재고 수량이 초과 하지 않았으나
초과 테스트 에서 실행한 코드를 예외를 발생시켜야 한다

예외가 발생하지 않으면 fail() 메서드를 호출하여
강제로 테스트 실패시켜 AssertionError 에러를 발생

2) 재고 수량 10개, 주문 수량 11개 일 때

  • NotEnoughStockException 예외 발생

    orderService.order → OrderItem.createOrderItem → item.removeStock(count) 호출

    createOrderItem을 만들 때 Item에서 removeStock을 호출하여
    removeStock에서 비즈니스 로직 실행

public abstract class Item {

// ...

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

3) 상품 취소 테스트

💻 코드 3

@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("주문 취소 시 상태는 CANCEL", OrderStatus.CANCEL, getOrder.getStatus());
        assertEquals("주문이 취소된 상품은 그만큼 재고가 증가해야 한다.", 10, item.getStockQuantity());

    }

📍 설명 3

1) 기능

  • given 절 : 주문 생성
  • when 절 : 주문 취소
  • then 절 : 주문 취소 후 재고가 정상적으로 복구 되었는지 확인

좋은 웹페이지 즐겨찾기