완벽하게 제어하기
class TestExample {
@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().getFirst().getName()).isEqualTo("아메리카노");
}
}
public ServiceClass {
public Order createOrder() {
LocalDateTime currentDateTime = LocalDateTime.now();
LocalTime currentTime = currentDateTime.toLocalTime();
if (currentTime.isBefore(SHOP_OPEN_TIME) || currentTime.isAfter(CLOSE_OPEN_TIME)) {
throw new IllegalArgumentException("주문 시간이 아닙니다. 관리자에게 문의하세요.");
}
return new Order(currentDateTime, beverages);
}
}
두 가지 상황에 대한 예시 코드의 핵심은 내가 제어할 수 없는 값을 어떻게 테스트할 것인가? 에 대한 내용이다.
좋은 테스트코드를 작성하기 위해서는 내가 제어할 수 없는 값을 상위 계층으로 옮기고, 메서드 내부에서는 주입되는 값을 기준으로 행동해야한다.
"나쁜 예시" 에 나왔듯 시간을 기준으로 행동하는 메서드가 있을 때 시간에 대한 제약사항이 생긴다면 실행 하는 시점에 따라 테스트가 성공할수도, 실패할 수도 있다.
잊지 말아야 할 점은 테스트 코드는 언제나 실패하거나 언제나 성공해야 하는 트랜잭션의 원자성과 같은 존재다.
좋은 예시에서는 시간을 외부 사용하는 시점에서 주입하게 되고, 메서드 내부에서는 주입 받는 값을 사용하는데 적절하게 쓰이고 있으니 테스트하기 편리하다.
이는 테스트코드에서 Given 절에서 필요한 시간 데이터를 생성해서 주입하면 되기 때문
이렇게 내부 시스템에서 내가 온전히 제어할 수 없다면 항상 상위 계층으로 빼거나, Mocking 을 통해 의도하는 값을 사용해서 언제나 테스트에 대한 신뢰를 보장해야한다.
앞으로는 코드를 작성할 때 이 질문을 끊임없이 던져보자.
내부 시스템에서 메서드를 완벽하게 제어할 수 있는가?
@DisplayName("주문 생성 시 주문 등록 시간을 기록한다.")
@Test
void registeredDateTime() {
// given
LocalDateTime registeredDateTime = LocalDateTime.now();
List<Product> products = List.of(
createProduct("001", 1000),
createProduct("002", 2000)
);
// when
Order order = Order.create(products, registeredDateTime);
// then
assertThat(order.getRegisteredDateTime()).isEqualTo(registeredDateTime);
}
추가적으로 위 테스트 코드를 보면, 시간을 외부에서 주입하기 때문에 좋은 테스트코드 처럼 보인다. 또 그렇게 설명을 했었다.
하지만 여기서 간과한 점은 테스트 코드 내에서도 변하는 값에 대한 신뢰를 보장하기 위해서 우리는 "상수" 를 이용하여 테스트 하는 것이 가장 바람직하다.
그 이유는 만약, LocalDateTime.now 라는 메서드를 한 번 호출 했다면 이 메서드를 검증 하거나 사용해야 하는 부분에 이 변수는 계속 따라다니게 된다.
즉 한 개의 변수가 테스트 코드 내에서 한 번 사용 되었다는 이유로 테스트 코드의 내용이 추가 될 때 마다 같이 쫓아다니며 동일한 값을 유도해야한다.
그래서 가능하다면 최대한 검증하는 값은 상수를 사용하고, 항상 내부 시스템에서 온전히 제어할 수 있도록 코드를 작성하는 의식적 연습이 필요하다.
Last updated