模拟 ZonedDateTime Java8

Mocking ZonedDateTime Java8

我有一个生成时间戳的模型构造函数 this.timestamp = null == timestamp ? ZonedDateTime.now().toInstant().toEpochMilli() : timestamp;

如何模拟ZonedDateTime? 我需要使用测试用例验证时间戳的值是以毫秒为单位的当前时间。

因为它是一个模型,所以在构造函数中注入一个单独的 clock class 的依赖是不可能的,我不想更改源代码。

这取决于你的class和你想做什么:

  1. 如果你想模拟 class 的所有属性,而 class 不是最终的,那么使用像 Mockito.[= 这样的模拟框架19=]

    MyClass mocked = Mockito.mock(MyClass.class);       
    Mockito.when(mocked.getTimestamp()).thenReturn(**/ your value **/ )
    
  2. 如果你的 class 是最终的,你只想模拟这个单一的 属性 或者 属性 是最终的:

您可以创建一个静态工厂,它为您提供Instant,然后在您的测试中替换该工厂。

 class TimeFactory {

  private static Supplier<Instant>  INSTANT_SUPPLIER = Instant::now;
  public static Instant getInstant(){ return INSTANT_SUPPLIER.get(); }
  public static void setInstantSupplier(Supplier<Instant> new){ INSTANT_SUPPLIER= supplier; } 
} 

在你的构造函数中:

this.timestamp = null == timestamp ? TimeFactory.getInstant().toEpochMilli() : timestamp;

现在在你的测试中,你可以使用 setter 方法:

 TimeFactory.setInstantSupplier(()-> /*Your value*/ )
 // create your object

测试后记得return默认供应商:

TimeFactory.setInstantSupplier(Instant::now);
  1. 如果你的 属性 不是最终版本,那么添加一个包 setter,可以在你的测试中使用。

  2. 下一个解决方案(虽然不推荐)是 use reflection。但这不是嘲笑,这是使用强制设置私有(事件最终)属性。

  3. 还有一个办法overwrite the clock for tests