일단 간단하게만 보면 now를 호출할 때 Clock만 모킹해서 넘겨주면 된다. Clock은 timezone(아마도 UTC일 것 같다.)을 기준으로 date와 time을 제공해준다. 기본적으로 Clock을 고정(fix) 시키지 않으면 디폴트로 OS에 설정된 타임존과 시간을 기준으로 현재 시간을 반환한다.
다행히 Clock은 fixed 메서드를 통해 모킹할 수 있고, 모킹한 Clock을 가지고 현재 시간을 구하게 하면 문제는 깔끔하게 해결할 수 있다.
// 지정한 날짜/시간으로 현재 시간을 고정시킨다. publicstaticvoidtimeTravelAt(LocalDateTime dateTime){ clock = Clock.fixed(dateTime.atOffset(zoneOffset).toInstant(), zoneOffset); }
publicstaticvoidtimeTravelAt(LocalTime time) { // 여기서 중요한 건 시간이고 날짜는 중요치 않다. clock = Clock.fixed(time.atDate(LocalDate.now()).atOffset(zoneOffset).toInstant(), zoneOffset); }
publicstaticvoidtimeTravelAt(LocalDate date) { // 여기서 중요한 건 날짜고 시간은 중요치 않다. clock = Clock.fixed(date.atStartOfDay().atOffset(zoneOffset).toInstant(), zoneOffset); }
// 모킹한 현재 시간을 다시 원래 현재 시간으로 되돌리는 메소드이다. publicstaticvoidreset() { clock = Clock.systemDefaultZone(); } }
타임머신이란 이름이 매우 몽환적인 분위기를 풍기는 것 같기도 하고, 참 매력적이다.
Clock.fixed 메소드의 예제는 아래를 참고하면 쉽게 이해할 수 있다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
publicclassClockTest { @Test publicvoidtestFixedClock() { // 2011년 1월 1일 1시 1분 0초 LocalDateTimedateTime= LocalDateTime.of(2011, 1, 1, 1, 1);
// UTC +09:00 서울/도쿄 기준 2011년 1월 1일 1시 1분 0초 Instantinstant= dateTime.atOffset(ZoneOffset.ofHours(9)).toInstant();
// UTC +09:00 2011년 1월 1일 1시 1분 0초를 UTC ±00:00 기준으로 변환한 Clock ClockfixedClock= Clock.fixed(instant, ZoneOffset.ofHours(0));
// UTC +09:00 기준의 시간을 UTC ±00:00 기준의 시간으로 변경했으므로 9시간만 빼면 된다. assertThat(LocalDateTime.now(fixedClock), is(LocalDateTime.of(2010, 12, 31, 16, 1))); } }