테스트가 어려운 영역을 분리하기테스트 코드2024. 9. 26. 22:18
Table of Contents
테스트가 어려운 코드 영역 구분
주문 메서드 작성
키오스크 주문은 10시 ~ 22시 사이로 가능하다. 그 시간 외에는 IllegalArgumentException 예외가 발생한다.
@Getter
public class CafeKiosk {
public static final LocalTime SHOP_OPEN_TIME = LocalTime.of(10, 0);
public static final LocalTime SHOP_CLOSE_TIME = LocalTime.of(22, 0);
private final List<Beverage> beverages = new ArrayList<>();
public Order createOrder() {
LocalDateTime currentDateTime = LocalDateTime.now();
LocalTime currentTime = currentDateTime.toLocalTime();
if(currentTime.isBefore(SHOP_OPEN_TIME) || currentTime.isAfter(SHOP_CLOSE_TIME)) {
throw new IllegalArgumentException("주문 시간이 아닙니다. 관리자에게 문의하세요.");
}
return new Order(currentDateTime, beverages);
}
}
테스트 코드 작성
아래 테스트는 통과할 수도, 통과하지 못할 수도 있다. createOrder() 메서드는 현재 시간인 currentDateTime을 사용한다. 테스트를 성공하기 위해서는 10시 ~ 22시 사이어야 하고, 그게 아니라면 테스트에 실패하게 된다.
class CafeKioskTest {
@Test
void createOrder() {
CafeKiosk cafeKiosk = new CafeKiosk();
Americano americano = new Americano();
cafeKiosk.add(americano);
Order order = cafeKiosk.createOrder();
assertThat(order.getBeverages()).hasSize(1);
assertThat(order.getBeverages().get(0).getName()).isEqualTo("아메리카노");
}
}
메서드 내부에서 현재 시간을 입력받고 있기 때문에 테스트에 어려움이 있다. 테스트에 어려움이 있는 영역을 식별하였기 때문에 이를 외부로 분리하자. 외부로 분리한다는 것은 파라미터로 입력받을 수 있도록 한다는 의미다.
아래는 현재 시간을 파라미터로 입력받을 수 있도록 하였다.
@Getter
public class CafeKiosk {
public static final LocalTime SHOP_OPEN_TIME = LocalTime.of(10, 0);
public static final LocalTime SHOP_CLOSE_TIME = LocalTime.of(22, 0);
private final List<Beverage> beverages = new ArrayList<>();
public Order createOrder(LocalDateTime dateTime) {
// LocalDateTime currentDateTime = LocalDateTime.now();
LocalTime currentTime = dateTime.toLocalTime();
if(currentTime.isBefore(SHOP_OPEN_TIME) || currentTime.isAfter(SHOP_CLOSE_TIME)) {
throw new IllegalArgumentException("주문 시간이 아닙니다. 관리자에게 문의하세요.");
}
return new Order(dateTime, beverages);
}
}
테스트가 어려운 부분을 외부로 분리하면서 항상 성공하는 테스트 코드를 작성할 수 있게 되었다. 또한 현재 시간을 직접 입력받기 때문에 경계값 테스트 또한 가능해졌다.
- createOrderWithCurrentTime() : 성공 테스트 케이스
- createOrderOutsideOpenTime() : 실패 테스트 케이스
결론
테스트하기 어려운 영역이 존재한다면 이를 외부로 분리할 수 없는지 생각해보자. 파라미터를 통해 직접 입력받을 수 있도록 한다면 테스트가 가능한 코드 또한 많아진다.
아래는 테스트를 어렵게 만드는 대표적인 예시이다.
- 관측할 때마다 다른 값에 의존하는 코드
- 현재 날짜/시간, 랜덤 값, 사용자 입력 …
- 외부 세계에 영향을 주는 코드
- 데이터베이스 기록, 메일 전송, 파일 기록 …