如何测试使用LocalDateTime.now()创建的日期

ibe*_*beu 7 java unit-testing date

我有这门课

class MyObject {
    private LocalDateTime date;

    public LocalDateTime getDate() { return this.date; }

    public void myMethod() {
        this.date = LocalDateTime.now();
    }
}
Run Code Online (Sandbox Code Playgroud)

如何测试日期是否正确设置?我无法模拟,now()因为它是静态的,如果我在测试中使用LocalDateTime,两个日期将不相同.

Jon*_*eet 10

我不能模拟now()因为它是静态的

确实 - 但幸运的是,你没有必要.相反,将"日期/时间提供程序"视为依赖项,并将其注入正常状态.java.time提供了这样的依赖:java.time.Clock.在测试中,您可以提供固定时钟Clock.fixed(...)(无需模拟)以及您使用的生产Clock.system(...).

然后将代码更改为:

class MyObject {
    private final Clock clock;
    private LocalDateTime date;

    public MyObject(Clock clock) {
        this.clock = clock;
    }

    public LocalDateTime getDate() {
        return this.date;
    }

    public void myMethod() {
        this.date = LocalDateTime.now(clock);
    }
}
Run Code Online (Sandbox Code Playgroud)

...或者你通常处理依赖关系.

  • @iberbeu:如果在夏时制更改时进行测试,或者系统时钟更改,则接受的答案将失败。我更喜欢将测试与系统时钟完全隔离-并使对时钟的依赖性明确。 (2认同)

Nic*_*tto 5

您可以在致电之前生成日期时间myMethod(),并确保此日期早于或等于所返回的日期getDate(),例如:

@Test
public void testDate() {
    MyObject object = new MyObject();
    // Get the current date time 
    LocalDateTime time = LocalDateTime.now();
    // Affect the current date time to the field date
    object.myMethod();
    // Make sure that it is before or equals
    Assert.assertTrue(time.isBefore(object.getDate()) || time.isEqual(object.getDate()));
}
Run Code Online (Sandbox Code Playgroud)

如果您不在乎向类添加耦合,则更好的方法可能是Supplier<LocalDateTime>在下一个类中提供一个:

public class MyObject {
    private final Supplier<LocalDateTime> supplier;
    private LocalDateTime date;

    public MyObject() {
        this(LocalDateTime::now);
    }

    public MyObject(final Supplier<LocalDateTime> supplier) {
        this.supplier = supplier;
    }

    public LocalDateTime getDate() { return this.date; }

    public void myMethod() {
        this.date = supplier.get();
    }
}
Run Code Online (Sandbox Code Playgroud)

这样,Supplier在您的测试用例中创建用于测试的目标将很容易。

例如,测试用例可以是:

@Test
public void testDate() {
    LocalDateTime time = LocalDateTime.now();
    MyObject object = new MyObject(() -> time);
    object.myMethod();
    Assert.assertTrue(time.isEqual(object.getDate()));
}
Run Code Online (Sandbox Code Playgroud)