在 Java 8 的 java.time API 中模拟时间

2022-08-31 09:44:43

Joda Time有一个很好的DateTimeUtils.setCurrentMillisFixed()来模拟时间。

这在测试中非常实用。

Java 8的java.time API中是否有等效的?


答案 1

最接近的是物体。您可以使用所需的任何时间(或从系统当前时间)创建 Clock 对象。所有 date.time 对象都有重载方法,这些方法将时钟对象替换为当前时间。因此,您可以使用依赖关系注入来注入具有特定时间的时钟:Clocknow

public class MyBean {
    private Clock clock;  // dependency inject
    ...
    public void process(LocalDate eventDate) {
      if (eventDate.isBefore(LocalDate.now(clock)) {
        ...
      }
    }
  }

有关更多详细信息,请参阅时钟 JavaDoc


答案 2

我使用了一个新类来隐藏创建并简化测试:Clock.fixed

public class TimeMachine {

    private static Clock clock = Clock.systemDefaultZone();
    private static ZoneId zoneId = ZoneId.systemDefault();

    public static LocalDateTime now() {
        return LocalDateTime.now(getClock());
    }

    public static void useFixedClockAt(LocalDateTime date){
        clock = Clock.fixed(date.atZone(zoneId).toInstant(), zoneId);
    }

    public static void useSystemDefaultZoneClock(){
        clock = Clock.systemDefaultZone();
    }

    private static Clock getClock() {
        return clock ;
    }
}
public class MyClass {

    public void doSomethingWithTime() {
        LocalDateTime now = TimeMachine.now();
        ...
    }
}
@Test
public void test() {
    LocalDateTime twoWeeksAgo = LocalDateTime.now().minusWeeks(2);

    MyClass myClass = new MyClass();

    TimeMachine.useFixedClockAt(twoWeeksAgo);
    myClass.doSomethingWithTime();

    TimeMachine.useSystemDefaultZoneClock();
    myClass.doSomethingWithTime();

    ...
}