Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
Tags
- 1차원 DP
- 2차원 dp
- 99클럽
- @Builder
- @GeneratedValue
- @GenericGenerator
- @NoargsConstructor
- @Transactional
- Actions
- Amazon EFS
- amazon fsx
- Android Studio
- ANSI SQL
- ApplicationEvent
- assertThat
- async/await
- AVG
- AWS
- Azure
- bind
- builder
- button
- c++
- c++ builder
- c03
- Callback
- case when
- CCW
- chat GPT
- CICD
Archives
- Today
- Total
기록
[단위테스트] 테스트하기 어려운 영역 분리: 현재 시간 의존성 해결 본문
1. 테스트하기 어려운 영역: 시간 의존성
소프트웨어에서 현재 시간(LocalDateTime.now())에 의존하는 코드는 테스트하기 어렵습니다. 이는 테스트 실행 시점에 따라 결과가 달라질 수 있기 때문입니다. 예를 들어:
- 테스트가 영업 시간 내에 실행되면 성공하지만, 영업 시간 외에 실행되면 실패합니다.
- 동일한 테스트 코드가 실행 시간에 따라 불안정한 결과를 초래합니다.
2. 문제점
아래의 기존 코드는 현재 시간에 직접적으로 의존하고 있어 테스트 실행 시마다 결과가 달라질 가능성이 있습니다:
public Order createOrder() {
LocalDateTime now = LocalDateTime.now();
LocalTime currentTime = now.toLocalTime();
if (currentTime.isBefore(SHOP_OPEN_TIME) || currentTime.isAfter(SHOP_CLOSE_TIME)){
throw new IllegalArgumentException("주문 시간이 아닙니다. 관리자에게 문의하세요.");
}
return new Order(LocalDateTime.now(), beverages);
}
문제점:
1. LocalDateTime.now() 호출 시점에 따라 결과가 달라질 수 있습니다.
2. 테스트 환경에서 현재 시간을 제어할 수 없어 영업 시간 내외의 동작을 모두 검증하기 어렵습니다.
3. 해결책: 외부에서 시간 주입
- 기본 동작에서는 현재 시간을 그대로 사용할 수 있도록 유지합니다.
- 테스트 시에는 외부에서 시간을 주입받아 다양한 시나리오를 검증할 수 있도록 메서드를 오버로딩합니다.
public Order createOrder() {
return createOrder(LocalDateTime.now());
}
// 테스트를 위해 외부에서 시각을 주입받는 오버로딩 메서드
public Order createOrder(LocalDateTime now) {
LocalTime currentTime = now.toLocalTime();
if (currentTime.isBefore(SHOP_OPEN_TIME) || currentTime.isAfter(SHOP_CLOSE_TIME)){
throw new IllegalArgumentException("주문 시간이 아닙니다. 관리자에게 문의하세요.");
}
return new Order(now, beverages);
}
4. 테스트 코드: 시간 의존성 분리 후 테스트
(1) 기본 동작 테스트
- 현재 시간을 기반으로 주문을 생성하는 기본 동작을 검증합니다.
@Test
@DisplayName("테스트를 실행하는 시간에 따라 실패할 수도 있는 테스트")
void createOrder() {
// Arrange
CafeKiosk cafeKiosk = new CafeKiosk();
Americano americano = new Americano();
cafeKiosk.add(americano);
// Act
Order order = cafeKiosk.createOrder();
// Assert
assertThat(cafeKiosk.getBeverages()).hasSize(1); // 음료가 1개인지 확인
}
문제점:
- 위 테스트는 실행 시간이 영업 시간 내에 있을 때만 성공합니다.
- 시간이 외부에서 고정되지 않았기 때문에 불안정한 테스트입니다.
(2) 테스트 가능한 코드로 변경
- 외부에서 고정된 시간을 주입하여 영업 시간 내 주문을 테스트합니다.
@Test
@DisplayName("Happy Case: 영업 시간 내에 주문 생성")
void createOrderWithCurrentTime() {
// Arrange
CafeKiosk cafeKiosk = new CafeKiosk();
Americano americano = new Americano();
cafeKiosk.add(americano);
// Act
Order order = cafeKiosk.createOrder(LocalDateTime.of(2023, 1, 17, 14, 0)); // 고정된 시간 주입
// Assert
assertThat(cafeKiosk.getBeverages()).hasSize(1); // 음료가 1개인지 확인
}
5. 결론: 외부 주입을 활용해 테스트 가능한 설계를 하라
테스트하기 어려운 영역(시간, 외부 시스템 등)은 외부에서 주입받는 설계를 통해 해결할 수 있습니다.
- 외부에서 값을 주입받아 테스트 시나리오를 제어할 수 있습니다.
- 기본 동작을 유지하면서도 다양한 시나리오에 대한 테스트를 작성할 수 있습니다.
'교육 > 강의' 카테고리의 다른 글
[TDD] Test Driven Development, Red-Green-Refactor (0) | 2025.01.23 |
---|---|
[단위테스트] 해피 케이스와 예외 케이스 (0) | 2025.01.21 |
[단위테스트] 수동 테스트 vs 자동화 테스트 : Junit5, AssertJ (0) | 2025.01.20 |
Practical Testing: 시작하면서 (0) | 2025.01.19 |
Comments