Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

3단계 - 테스트를 통한 코드 보호 #823

Merged
merged 29 commits into from
Feb 10, 2025
Merged
Show file tree
Hide file tree
Changes from 20 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
98a14af
메뉴그룹(MenuGroup) 테스트 코드 추가
skdev0619 Feb 3, 2025
5dd3cd7
상품(Product) 테스트 코드 추가
skdev0619 Feb 3, 2025
668dad4
메뉴(Menu) 등록 테스트 코드 추가
skdev0619 Feb 3, 2025
176fd28
메뉴(Menu) 수정, 전시/비전시, 조회 테스트 코드 추가
skdev0619 Feb 3, 2025
ecda79c
주문 생성 테스트 코드 추가
skdev0619 Feb 3, 2025
05f1ae7
주문 수락 테스트 코드 추가
skdev0619 Feb 3, 2025
247f6fe
음식제공됨 테스트 코드 추가
skdev0619 Feb 3, 2025
cf5a26b
배달 중, 배달완료 테스트 코드 추가
skdev0619 Feb 3, 2025
f421d13
주문 완료 테스트 코드 추가
skdev0619 Feb 3, 2025
f048ab0
주문 조회 테스트 코드 추가
skdev0619 Feb 3, 2025
b889deb
주문 테이블 등록, 배정 테스트 코드 추가
skdev0619 Feb 3, 2025
e96e419
주문 테이블 정리, 고객의 수 변경, 조회 테스트 코드 추가
skdev0619 Feb 3, 2025
4520add
textFixture 적용
skdev0619 Feb 3, 2025
6e274fb
@Nested 적용
skdev0619 Feb 5, 2025
c41369b
AssertAll 적용
skdev0619 Feb 5, 2025
12de231
ReflectionTestUtils 적용
skdev0619 Feb 5, 2025
bea5bdf
MenuGroup 테스트 속도 개선
skdev0619 Feb 5, 2025
20f2580
Product 테스트 속도 개선
skdev0619 Feb 5, 2025
d4b58c4
Menu 테스트 속도 개선
skdev0619 Feb 5, 2025
844c123
Order, OrderTable 테스트 속도 개선
skdev0619 Feb 5, 2025
0ef38a0
Fake 클래스 패키지 변경
skdev0619 Feb 6, 2025
cf594ca
메뉴 요구사항 통합
skdev0619 Feb 6, 2025
76f58e9
OrderTable ReflectionTestUtils 제거
skdev0619 Feb 6, 2025
da95afc
Order ReflectionTestUtils 제거
skdev0619 Feb 6, 2025
ad64f08
fake 패키지 생성
skdev0619 Feb 7, 2025
6ea560e
Fixture setter 제거
skdev0619 Feb 7, 2025
c0344aa
메뉴를 빈 상품 또는 상품 없이 등록하면 예외가 발생한다
skdev0619 Feb 7, 2025
46a206b
orderTableId 사용하지 않도록 변경 & OrderFixture 수정
skdev0619 Feb 7, 2025
5b12cef
OrderFixture 정리 및 적용
skdev0619 Feb 10, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
173 changes: 86 additions & 87 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,16 @@ docker compose -p kitchenpos up -d
### 상품(product)
**상품이란?**
> 햄버거, 감자튀김, 치킨과 같은 각각의 개별적인 음식을 상품이라고 부른다.
- [ ] 상품을 등록할 수 있다
- [ ] 상품명과 가격을 입력할 수 있다
- [ ] 상품명과 가격은 반드시 입력되어야 한다
- [ ] 상품명은 비속어가 있으면 등록할 수 없다
- [ ] 가격은 0원 이상이어야 한다
- [ ] 상품 가격을 수정할 수 있다
- [ ] 상품 가격은 0원 이상이어야 한다
- [ ] 메뉴의 가격이 메뉴에 속한 상품들의 가격 총 합보다 클 경우, 그 메뉴는 유효하지 않다.
- [ ] 유효하지 않은 메뉴는 노출하지 않는다
- [ ] 모든 상품을 조회할 수 있다
- [x] 상품을 등록할 수 있다
- [x] 상품명과 가격을 입력할 수 있다
- [x] 상품명과 가격은 반드시 입력되어야 한다
- [x] 상품명은 비속어가 있으면 등록할 수 없다
- [x] 가격은 0원 이상이어야 한다
- [x] 상품 가격을 수정할 수 있다
- [x] 상품 가격은 0원 이상이어야 한다
- [x] 메뉴의 가격이 메뉴에 속한 상품들의 가격 총 합보다 클 경우, 그 메뉴는 유효하지 않다.
- [x] 유효하지 않은 메뉴는 노출하지 않는다
- [x] 모든 상품을 조회할 수 있다

### 메뉴(menu)
**메뉴란?**
Expand All @@ -46,34 +46,33 @@ ex)
> 치킨버거 > 치킨버거세트 > 콜라 > 감자튀김
> 새우버거 > 새우버거세트 > 사이다 > 치즈스틱
```
- [ ] 메뉴를 등록할 수 있다
- [ ] 단일 또는 여러 상품을 조합하여 메뉴를 만들 수 있다
- [ ] 각 메뉴를 구성하는 상품과 그 수량을 선택할 수 있다
- [ ] 각 메뉴를 구성하는 상품의 수량은 0이상이어야 한다
- [ ] 메뉴는 메뉴명, 가격, 메뉴판 전시 여부(전시 O/ 전시 X) 정보를 가진다
- [ ] 메뉴명, 가격, 메뉴판 전시 여부는 반드시 입력되어야 한다
- [ ] 메뉴명에 비속어가 있으면 입력할 수 없다
- [ ] 메뉴의 가격은 0원 이상이어야 한다
- [ ] 메뉴의 가격이 포함된 상품 가격 총합과 동일하거나 할인된 가격일 경우만 등록 가능하다
- [ ] 메뉴는 하나의 메뉴그룹을 가진다

- [ ] 메뉴는 가격을 수정할 수 있다
- [ ] 메뉴의 가격이 0원 이상이어야 한다
- [ ] 메뉴의 가격은 포함된 상품 가격 총합과 동일하거나 할인된 가격으로만 수정할 수 있다

- [ ] 메뉴판에 메뉴를 전시한다
- [ ] 메뉴판 전시 여부를 O로 변경한다
- [ ] 메뉴의 가격이 포함된 상품 가격 총합과 동일하거나 할인된 가격인 경우만 전시할 수 있다

- [ ] 메뉴판에서 메뉴를 내린다
- [ ] 메뉴판 전시 여부를 X로 변경한다
- [ ] 모든 메뉴를 조회할 수 있다
- [x] 메뉴를 등록할 수 있다
- [x] 단일 또는 여러 상품을 조합하여 메뉴를 만들 수 있다
- [x] 각 메뉴를 구성하는 상품과 그 수량을 선택할 수 있다
- [x] 각 메뉴를 구성하는 상품의 수량은 0이상이어야 한다
- [x] 메뉴는 메뉴명, 가격, 메뉴판 전시 여부(전시 O/ 전시 X), 메뉴그룹을 가진다
- [x] 메뉴명, 가격은 반드시 입력되어야 한다
- [x] 메뉴명에 비속어가 있으면 입력할 수 없다
- [x] 메뉴의 가격은 0원 이상이어야 한다
- [x] 메뉴의 가격이 포함된 상품 가격 총합과 동일하거나 할인된 가격일 경우만 등록 가능하다

- [x] 메뉴는 가격을 수정할 수 있다
- [x] 메뉴의 가격이 0원 이상이어야 한다
- [x] 메뉴의 가격은 포함된 상품 가격 총합과 동일하거나 할인된 가격으로만 수정할 수 있다

- [x] 메뉴판에 메뉴를 전시한다
- [x] 메뉴판 전시 여부를 O로 변경한다
- [x] 메뉴의 가격이 포함된 상품 가격 총합과 동일하거나 할인된 가격인 경우만 전시할 수 있다

- [x] 메뉴판에서 메뉴를 내린다
- [x] 메뉴판 전시 여부를 X로 변경한다
- [x] 모든 메뉴를 조회할 수 있다

### 메뉴 그룹(menu_group)
- [ ] 메뉴판의 메뉴그룹명을 등록할 수 있다
- [ ] 메뉴그룹명은 반드시 입력되어야 한다
- [ ] 메뉴그룹명은 공백만 입력되어서는 안된다
- [ ] 모든 메뉴 그룹을 조회할 수 있다
- [x] 메뉴판의 메뉴그룹명을 등록할 수 있다
- [x] 메뉴그룹명은 반드시 입력되어야 한다
- [x] 메뉴그룹명은 공백만 입력되어서는 안된다
- [x] 모든 메뉴 그룹을 조회할 수 있다

### 주문(Order)
**주문이란?**
Expand All @@ -86,63 +85,63 @@ ex)
- 매장 내 취식(EAT_IN)하는 고객의 경우, 테이블이 배정되어야 한다
- 테이블 내에서 주문 내역을 기반으로 주문이 이루어진다
```
- [ ] 주문 테이블을 등록할 수 있다
- [ ] 테이블에 이름을 지정할 수 있다
- [ ] 테이블 이름은 반드시 입력되어야 한다
- [ ] 테이블 이름은 공백만 입력되어서는 안된다
- [ ] 테이블에 있는 고객의 수를 확인할 수 있다
- [ ] 테이블 최초 등록 시에는 고객의 수를 0명으로 등록한다
- [ ] 테이블 사용 유무(사용 중/사용 안함)을 알 수 있다
- [ ] 테이블 최초 등록 시에는 테이블 사용 안함으로 등록한다

- [ ] 주문 테이블에 고객이 배정된다
- [ ] 테이블의 사용 유무를 사용 중으로 변경한다

- [ ] 주문 테이블을 정리한다
- [ ] 주문 상태가 완료가 아니면 정리할 수 없다
- [ ] 고객의 수 0명, 테이블 사용유무 사용안함으로 변경한다
- [ ] 테이블에 앉아있는 고객의 수를 변경할 수 있다
- [ ] 고객의 수를 0 미만으로는 변경할 수 없다
- [ ] 테이블의 사용유무가 사용안함이면 안된다
- [ ] 모든 주문 테이블을 조회할 수 있다
- [x] 주문 테이블을 등록할 수 있다
- [x] 테이블에 이름을 지정할 수 있다
- [x] 테이블 이름은 반드시 입력되어야 한다
- [x] 테이블 이름은 공백만 입력되어서는 안된다
- [x] 테이블에 있는 고객의 수를 확인할 수 있다
- [x] 테이블 최초 등록 시에는 고객의 수를 0명으로 등록한다
- [x] 테이블 사용 유무(사용 중/사용 안함)을 알 수 있다
- [x] 테이블 최초 등록 시에는 테이블 사용 안함으로 등록한다

- [x] 주문 테이블에 고객이 배정된다
- [x] 테이블의 사용 유무를 사용 중으로 변경한다

- [x] 주문 테이블을 정리한다
- [x] 주문 상태가 완료가 아니면 정리할 수 없다
- [x] 고객의 수 0명, 테이블 사용유무 사용안함으로 변경한다
- [x] 테이블에 앉아있는 고객의 수를 변경할 수 있다
- [x] 고객의 수를 0 미만으로는 변경할 수 없다
- [x] 테이블의 사용유무가 사용안함이면 안된다
- [x] 모든 주문 테이블을 조회할 수 있다

### 주문(orders)
주문의 종류에 따른 주문 상태의 변화는 아래 도식도를 참고하도록 한다
![설명](./assets/OrderFlowChart.png)

- [ ] 주문은 생성할 수 있다
- [ ] 주문의 종류는 배달(DELIVERY), 포장(TAKEOUT), 매장 내 취식(EAT_IN) 중 선택할 수 있다
- [ ] 어떤 메뉴를 몇 개 시킬지에 대한 주문 상세 내역이 1개 이상 있어야 한다
- [ ] 배달, 포장의 경우, 주문한 메뉴의 수량이 0이상이어야 한다
- [ ] 메뉴판에 전시되지 않은 메뉴는 주문할 수 없다
- [ ] 메뉴의 가격과 주문 내역의 가격은 동일해야 한다
- [ ] 배달의 경우, 배달 주소가 반드시 입력되어야 한다
- [ ] 배달 주소는 공백만 입력되어서는 안된다
- [ ] 매장 내 취식의 경우, 매장 내 배정된 주문 테이블이 있어야 한다
- [ ] 주문 테이블의 사융 유무가 사용 중이어야 한다
- [ ] 주문의 상태는 '대기(WAITING)'가 된다
- [ ] 대기하고 있는 주문을 수락한다
- [ ] 주문의 상태가 대기(WAITING)일 때 주문 수락이 가능하다
- [x] 주문은 생성할 수 있다
- [x] 주문의 종류는 배달(DELIVERY), 포장(TAKEOUT), 매장 내 취식(EAT_IN) 중 선택할 수 있다
- [x] 어떤 메뉴를 몇 개 시킬지에 대한 주문 상세 내역이 1개 이상 있어야 한다
- [x] 배달, 포장의 경우, 주문한 메뉴의 수량이 0이상이어야 한다
- [x] 메뉴판에 전시되지 않은 메뉴는 주문할 수 없다
- [x] 메뉴의 가격과 주문 내역의 가격은 동일해야 한다
- [x] 배달의 경우, 배달 주소가 반드시 입력되어야 한다
- [x] 배달 주소는 공백만 입력되어서는 안된다
- [x] 매장 내 취식의 경우, 매장 내 배정된 주문 테이블이 있어야 한다
- [x] 주문 테이블의 사융 유무가 사용 중이어야 한다
- [x] 주문의 상태는 '대기(WAITING)'가 된다
- [x] 대기하고 있는 주문을 수락한다
- [x] 주문의 상태가 대기(WAITING)일 때 주문 수락이 가능하다
- [ ] 배달 주문의 경우, 라이더에게 주문 정보(주문 총액, 배달 주소)를 제공하여 배달하도록 한다
- [ ] 주문의 상태를 주문 수락(ACCEPTED)으로 변경한다
- [ ] 수락한 주문을 기반으로 음식을 제공한다
- [ ] 수락한 주문의 상태는 주문 수락(ACCEPTED)이어야 한다
- [ ] 음식 제공 후, 주문 상태를 음식 제공됨(SERVED)으로 변경한다
- [ ] 배달 주문의 경우, 배달을 시작한다
- [ ] 주문의 상태가 음식 제공됨(SERVED)일 때 배달 가능하다
- [ ] 주문의 상태를 배달 중(DELIVERING)으로 변경한다
- [ ] 배달 주문의 경우, 배달이 완료한다
- [ ] 주문의 상태가 배달 중(DELIVERING)인 경우만 배달 완료할 수 있다
- [ ] 주문 상태를 배달 완료(DELIVERED)으로 변경한다
- [ ] 주문을 완료한다
- [ ] 주문 유형에 따라 아래와 같은 주문 상태일 때만 완료할 수 있다
- [ ] 배달은 주문 상태가 배달 완료(DELIVERED)여야 한다
- [ ] 매장 내 취식/포장은 주문 상태가 음식 제공됨(SERVED)이어야 한다
- [ ] 매장 내 취식의 경우, 해당 테이블에 미완료된 주문이 없다면 테이블을 정리한다
- [ ] 고객의 수를 0명으로 변경한다
- [ ] 주문 테이블의 사용유무가 사용안함으로 변경한다
- [ ] 주문의 상태를 주문완료(COMPLETED)로 변경한다
- [ ] 모든 주문 목록을 조회할 수 있다
- [x] 주문의 상태를 주문 수락(ACCEPTED)으로 변경한다
- [x] 수락한 주문을 기반으로 음식을 제공한다
- [x] 수락한 주문의 상태는 주문 수락(ACCEPTED)이어야 한다
- [x] 음식 제공 후, 주문 상태를 음식 제공됨(SERVED)으로 변경한다
- [x] 배달 주문의 경우, 배달을 시작한다
- [x] 주문의 상태가 음식 제공됨(SERVED)일 때 배달 가능하다
- [x] 주문의 상태를 배달 중(DELIVERING)으로 변경한다
- [x] 배달 주문의 경우, 배달이 완료한다
- [x] 주문의 상태가 배달 중(DELIVERING)인 경우만 배달 완료할 수 있다
- [x] 주문 상태를 배달 완료(DELIVERED)으로 변경한다
- [x] 주문을 완료한다
- [x] 주문 유형에 따라 아래와 같은 주문 상태일 때만 완료할 수 있다
- [x] 배달은 주문 상태가 배달 완료(DELIVERED)여야 한다
- [x] 매장 내 취식/포장은 주문 상태가 음식 제공됨(SERVED)이어야 한다
- [x] 매장 내 취식의 경우, 해당 테이블에 미완료된 주문이 없다면 테이블을 정리한다
- [x] 고객의 수를 0명으로 변경한다
- [x] 주문 테이블의 사용유무가 사용안함으로 변경한다
- [x] 주문의 상태를 주문완료(COMPLETED)로 변경한다
- [x] 모든 주문 목록을 조회할 수 있다

## 용어 사전

Expand Down
20 changes: 8 additions & 12 deletions src/main/java/kitchenpos/application/ProductService.java
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
package kitchenpos.application;

import kitchenpos.domain.Menu;
import kitchenpos.domain.MenuProduct;
import kitchenpos.domain.MenuRepository;
import kitchenpos.domain.Product;
import kitchenpos.domain.ProductRepository;
import kitchenpos.domain.*;
import kitchenpos.infra.PurgomalumClient;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
Expand All @@ -22,9 +18,9 @@ public class ProductService {
private final PurgomalumClient purgomalumClient;

public ProductService(
final ProductRepository productRepository,
final MenuRepository menuRepository,
final PurgomalumClient purgomalumClient
final ProductRepository productRepository,
final MenuRepository menuRepository,
final PurgomalumClient purgomalumClient
) {
this.productRepository = productRepository;
this.menuRepository = menuRepository;
Expand Down Expand Up @@ -55,16 +51,16 @@ public Product changePrice(final UUID productId, final Product request) {
throw new IllegalArgumentException();
}
final Product product = productRepository.findById(productId)
.orElseThrow(NoSuchElementException::new);
.orElseThrow(NoSuchElementException::new);
product.setPrice(price);
final List<Menu> menus = menuRepository.findAllByProductId(productId);
for (final Menu menu : menus) {
BigDecimal sum = BigDecimal.ZERO;
for (final MenuProduct menuProduct : menu.getMenuProducts()) {
sum = sum.add(
menuProduct.getProduct()
.getPrice()
.multiply(BigDecimal.valueOf(menuProduct.getQuantity()))
menuProduct.getProduct()
.getPrice()
.multiply(BigDecimal.valueOf(menuProduct.getQuantity()))
);
}
if (menu.getPrice().compareTo(sum) > 0) {
Expand Down
8 changes: 8 additions & 0 deletions src/main/java/kitchenpos/domain/JpaMenuGroupRepository.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package kitchenpos.domain;

import org.springframework.data.jpa.repository.JpaRepository;

import java.util.UUID;

public interface JpaMenuGroupRepository extends MenuGroupRepository, JpaRepository<MenuGroup, UUID> {
}
15 changes: 15 additions & 0 deletions src/main/java/kitchenpos/domain/JpaMenuRepository.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package kitchenpos.domain;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;

import java.util.List;
import java.util.UUID;

public interface JpaMenuRepository extends MenuRepository, JpaRepository<Menu, UUID> {
List<Menu> findAllByIdIn(List<UUID> ids);

@Query("select m from Menu m join m.menuProducts mp where mp.product.id = :productId")
List<Menu> findAllByProductId(@Param("productId") UUID productId);
}
9 changes: 9 additions & 0 deletions src/main/java/kitchenpos/domain/JpaOrderRepository.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package kitchenpos.domain;

import org.springframework.data.jpa.repository.JpaRepository;

import java.util.UUID;

public interface JpaOrderRepository extends OrderRepository, JpaRepository<Order, UUID> {
boolean existsByOrderTableAndStatusNot(OrderTable orderTable, OrderStatus status);
}
8 changes: 8 additions & 0 deletions src/main/java/kitchenpos/domain/JpaOrderTableRepository.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package kitchenpos.domain;

import org.springframework.data.jpa.repository.JpaRepository;

import java.util.UUID;

public interface JpaOrderTableRepository extends OrderTableRepository, JpaRepository<OrderTable, UUID> {
}
10 changes: 10 additions & 0 deletions src/main/java/kitchenpos/domain/JpaProductRepository.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package kitchenpos.domain;

import org.springframework.data.jpa.repository.JpaRepository;

import java.util.List;
import java.util.UUID;

public interface JpaProductRepository extends ProductRepository, JpaRepository<Product, UUID> {
List<Product> findAllByIdIn(List<UUID> ids);
}
12 changes: 9 additions & 3 deletions src/main/java/kitchenpos/domain/MenuGroupRepository.java
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
package kitchenpos.domain;

import org.springframework.data.jpa.repository.JpaRepository;

import java.util.List;
import java.util.Optional;
import java.util.UUID;

public interface MenuGroupRepository extends JpaRepository<MenuGroup, UUID> {
public interface MenuGroupRepository {
MenuGroup save(MenuGroup menuGroup);

Optional<MenuGroup> findById(UUID id);

List<MenuGroup> findAll();
}

19 changes: 11 additions & 8 deletions src/main/java/kitchenpos/domain/MenuRepository.java
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
package kitchenpos.domain;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;

import java.util.List;
import java.util.Optional;
import java.util.UUID;

public interface MenuRepository extends JpaRepository<Menu, UUID> {
List<Menu> findAllByIdIn(List<UUID> ids);
public interface MenuRepository {
Menu save(Menu menu);

Optional<Menu> findById(UUID id);

List<Menu> findAll();

@Query("select m from Menu m join m.menuProducts mp where mp.product.id = :productId")
List<Menu> findAllByProductId(@Param("productId") UUID productId);
List<Menu> findAllByProductId(UUID productId);

List<Menu> findAllByIdIn(List<UUID> ids);
}

13 changes: 10 additions & 3 deletions src/main/java/kitchenpos/domain/OrderRepository.java
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
package kitchenpos.domain;

import org.springframework.data.jpa.repository.JpaRepository;

import java.util.List;
import java.util.Optional;
import java.util.UUID;

public interface OrderRepository extends JpaRepository<Order, UUID> {
public interface OrderRepository {
Order save(Order order);

Optional<Order> findById(UUID id);

List<Order> findAll();

boolean existsByOrderTableAndStatusNot(OrderTable orderTable, OrderStatus status);
}

11 changes: 8 additions & 3 deletions src/main/java/kitchenpos/domain/OrderTableRepository.java
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
package kitchenpos.domain;

import org.springframework.data.jpa.repository.JpaRepository;

import java.util.List;
import java.util.Optional;
import java.util.UUID;

public interface OrderTableRepository extends JpaRepository<OrderTable, UUID> {
public interface OrderTableRepository {
OrderTable save(OrderTable orderTable);

Optional<OrderTable> findById(UUID id);

List<OrderTable> findAll();
}
Loading