요약

  1. 도메인에서 시간 관련 검증을 해야하는 상황에서 테스트 코드를 작성해야함.
  2. 테스트 코드에서 단순하게 LocalDate.now() 를 사용하면, 로컬 환경에 따라 테스트 코드의 결과가 달라지는 문제 발생
  3. LocalDate.now() 에서 사용하는 Clock 를 모킹하여 테스트 코드 신뢰도를 높힘

문제상황

구현 코드 내부에서 LocalDate.now() 를 호출하여 사용 하는 로직이 있었다.

@Embeddable
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class StartingDate {

    @Column(name = "starting_date", nullable = false)
    private LocalDate startingDate;

    public StartingDate(final LocalDate startingDate) {
        validateDate(startingDate);
        this.startingDate = startingDate;
    }

    private void validateDate(final LocalDate startingDate) {
        if (**LocalDate.now().isAfter(startingDate)**) {
            throw new IllegalArgumentException("이미 지난 날짜는 활동 시작일로 할 수 없습니다.");
        }
    }

    public boolean isPassed() {
        return startingDate.isBefore(LocalDate.now());
    }

테스트 코드는 다음과 같이 작성 하였다.

@ParameterizedTest
    @MethodSource("correctStartingDateProvider")
    @DisplayName("활동 시작일 입력받아 객체를 생성한다. 활동 시작일은 과거의 날짜가 될 수 없다.")
    void create(final LocalDate startingDate) {
        //when, then
        assertThatCode(() -> new StartingDate(startingDate)).doesNotThrowAnyException();
    }

    private static Stream<Arguments> correctStartingDateProvider() {
        return Stream.of(
                Arguments.of(LocalDate.of(2023, 2, 16)),
                Arguments.of(LocalDate.of(2023, 2, 17)));
    }

이렇게 되니 문제점이 하나 발생 했다. 작성일 기준 현재 날짜2023년 2월 16일 이다. 현재는 해당 테스트코드가 문제 없이 통과한다.

하지만 내일인 2023년 2월 17일이 된다면 startingDate2023년 2월 16일 인 경우 테스트는 실패한다.

하루가 더 지나면 모든 경우가 다 실패한다.

테스트를 돌릴 때마다 결과가 다르면 신뢰도가 전혀 없는 테스트라고 생각하기 때문에, 해당 테스트 코드가 제대로 된 역할을 한다고 말할수가 없었다.

그래서 개선 해보기로 하였다.