사용방법

Javadoc 보기

설치

Maven을 사용하는 경우

<dependency>
	<groupId>com.github.perfectacle</groupId>
	<artifactId>time-machine</artifactId>
	<version>1.0.0</version>
</dependency>

Gradle을 사용하는 경우

implementation 'com.github.perfectacle:time-machine:1.0.0'

번역 문서

Java 8 Date/Time API의 now() 메서드 사용을 멈춰라.

Java 8 Date/Time API의 now() 메서드를 사용하는 코드가 있다고 가정해보자.

public class SomeClass {
    public static boolean someMethod() {
        return someMethod2();
    }
    
    private static boolean someMethod2() {
        return LocalTime.now().isAfter(LocalTime.of(12, 0, 0));
    }
}

시간은 통제 불가능 영역이다.

public class SomeClassTest {
    // 이 테스트는 오후에만 통과된다.
    @Test
    void someMethod() {
        assertTrue(SomeClass.someMethod());
    }
}

따라서 우리는 의미 없는 파라미터(현재 시간)을 계속해서 넘겨줘야한다.

public class SomeClass {
    public static boolean someMethod(final LocalTime now) {
        return someMethod2(now);
    }
    
    private static boolean someMethod2(final LocalTime now) {
        return now.isAfter(LocalTime.of(12, 0, 0));
    }
}

우리는 의미 없는 행위(파라미터를 넘기는)를 반복함으로써 시간을 통제할 수 있다.

public class SomeClassTest {
    // 이 테스트는 파라미터(현재 시간)를 넘김으로써 언제든 성공하는 테스트가 됐다.
    @Test
    void someMethod() {
        assertTrue(SomeClass.someMethod(LocalTime.of(13, 0, 0)));
    }
}

Time Machine을 사용해라.

public 메서드 내부에서 수 십개의 private 메서드를 사용한다면, 매번 현재 시간을 파라미터로써 넘길 것인가?
이런 비효율성을 제거하기 위해 Time Machine을 사용해야한다.

다양한 종류의 now 메서드를 사용하라

public class SomeClass {
    public static boolean someMethod() {
        return someMethod2();
    }
    
    private static boolean someMethod2() {
        return TimeMachine.nowOfLocalTime().isAfter(LocalTime.of(12, 0, 0));
    }
}

다양한 종류의 Java 8 Date/Time API를 사용해서 시간 여행을 떠나라.

public class SomeClassTest {
    // 이 테스트는 항상 통과한다.
    @Test
    void someMethod() {
        TimeMachine.travelAt(LocalTime.of(13, 0, 0));
        assertTrue(SomeClass.someMethod());
    }
}

현실 세계의 현재 시간을 사용하기 위해 Time Machine을 리셋해라.

public class SomeClassTest {
    @Test
    void whenNotTraveled() {
        // 다른 테스트의 영향을 받지 않으려면 Time Machine을 리셋해야한다.
        TimeMachine.reset();
    
        final Instant nowOfInstant = Instant.now();
        final Instant nowOfInstantWithTimeMachine = TimeMachine.nowOfInstant();
    
        assertEquals(nowOfInstant.minusNanos(nowOfInstant.getNano()), nowOfInstantWithTimeMachine.minusNanos(nowOfInstantWithTimeMachine.getNano()));
        assertEquals(ZonedDateTime.now(ZoneOffset.UTC).withNano(0), TimeMachine.nowOfZonedDateTime().withNano(0));
        assertEquals(OffsetDateTime.now(ZoneOffset.UTC).withNano(0), TimeMachine.nowOfOffsetDateTime().withNano(0));
        assertEquals(OffsetTime.now(ZoneOffset.UTC).withNano(0), TimeMachine.nowOfOffsetTime().withNano(0));
        assertEquals(LocalDateTime.now(ZoneOffset.UTC).withNano(0), TimeMachine.nowOfLocalDateTime().withNano(0));
        assertEquals(LocalDate.now(ZoneOffset.UTC), TimeMachine.nowOfLocalDate());
        assertEquals(LocalTime.now(ZoneOffset.UTC).withNano(0), TimeMachine.nowOfLocalTime().withNano(0));
    }
}