-
[스프링부트/웹 애플리케이션 개발]주문 도메인 개발-2스프링&스프링부트 2023. 1. 5. 13:13
주문 기능 테스트
package jpabook.jpashop.service; 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.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; import org.springframework.transaction.annotation.Transactional; import javax.persistence.EntityManager; import static org.junit.Assert.*; import static org.junit.Assert.assertEquals; @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); //반복적으로 사용하니까 extract Method 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("상품 주문시 상태는 Order", OrderStatus.ORDER, getOrder.getStatus()); assertEquals("주문한 상품 종류 수가 정확해야 한다.", 1, getOrder.getOrderItems().size()); assertEquals("주문 가격은 가격*수량이다.", 10000*orderCount, getOrder.getTotalPrice()); assertEquals("주문 수량만큼 재고가 줄어야한다.", 8, book.getStockQuantity()); } //예외처리 test하는 것 중요함 //remove의 별도 단위테스트있는게 좋음 @Test(expected = NotEnoughStockException.class) public void 상품주문_재고수량초과()throws Exception { //given Member member = createMember(); Item item = createBook("JPA책", 10000, 10); int orderCount = 11; //when orderService.order(member.getId(), item.getId(), orderCount); //then fail("재고 수량 부족 예외가 발생해야한다."); } @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()); } 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; } //정말 좋은 테스트 > 단위 테스트 의미있게 }
주문 검색 기능
- JPA에서 동적쿼리 해결?
방법1. JPQL 사용, 실무에서 사용하지 않음
public List<Order> findAllByString(OrderSearch orderSearch) { //language=JPAQL String jpql = "select o From Order o join o.member m"; boolean isFirstCondition = true; //주문 상태 검색 if (orderSearch.getOrderStatus() != null) { if (isFirstCondition) { jpql += " where"; isFirstCondition = false; } else { jpql += " and"; } jpql += " o.status = :status"; } //회원 이름 검색 if (StringUtils.hasText(orderSearch.getMemberName())) { if (isFirstCondition) { jpql += " where"; isFirstCondition = false; } else { jpql += " and"; } jpql += " m.name like :name"; } TypedQuery<Order> query = em.createQuery(jpql, Order.class) .setMaxResults(1000); //최대 1000건 if (orderSearch.getOrderStatus() != null) { query = query.setParameter("status", orderSearch.getOrderStatus()); } if (StringUtils.hasText(orderSearch.getMemberName())) { query = query.setParameter("name", orderSearch.getMemberName()); } return query.getResultList(); }
- mybatis 사용 이유 > 동적 쿼리에서 편리함
방법2. JPA Criteria > 실무에서 사용하지 않음, 유지보수 불가능
public List<Order> findAllByCriteria(OrderSearch orderSearch) { CriteriaBuilder cb = em.getCriteriaBuilder(); CriteriaQuery<Order> cq = cb.createQuery(Order.class); Root<Order> o = cq.from(Order.class); Join<Order, Member> m = o.join("member", JoinType.INNER); //회원과 조인 List<Predicate> criteria = new ArrayList<>(); //주문 상태 검색 if (orderSearch.getOrderStatus() != null) { Predicate status = cb.equal(o.get("status"), orderSearch.getOrderStatus()); criteria.add(status); } //회원 이름 검색 if (StringUtils.hasText(orderSearch.getMemberName())) { Predicate name = cb.like(m.<String>get("name"), "%" + orderSearch.getMemberName() + "%"); criteria.add(name); } cq.where(cb.and(criteria.toArray(new Predicate[criteria.size()]))); TypedQuery<Order> query = em.createQuery(cq).setMaxResults(1000); //최대 1000건 return query.getResultList(); }
방법3. . Querydsl
728x90'스프링&스프링부트' 카테고리의 다른 글
[스프링부트/웹 애플리케이션 개발]회원 목록 조회, 상품 등록, 상품 목록, 상품 수정 (0) 2023.01.05 [스프링부트/웹 애플리케이션 개발]홈 화면과 레이아웃, 부트스트랩 적용, 회원등록 (0) 2023.01.05 [스프링부트/웹 애플리케이션 개발]주문 도메인 개발-1 (0) 2023.01.05 [스프링부트/웹 애플리케이션 개발]상품 엔티티 개발 (0) 2023.01.04 [스프링부트/웹 애플리케이션 개발]회원 기능 테스트 (0) 2023.01.04