有没有办法使用规范来模拟 LocalDateTime 时间戳

Is there a way to mock LocalDateTime timestamp using specs

我应该为一个库的集成测试做出贡献,该库依赖于 specs,底层实现是用 Scala 编写的。测试更倾向于与某些 timestamp 属性流动的事件流。

以下存根是实际实现的部分

private def eligibleForRecentPost(optionalPost: Option[SearchEntity]): Boolean = {
    optionalSearch.map(search => search.timestamp)
      .exists(searchTime => searchTime >= LocalDateTime.now()
        .minusDays(recencyDurationInDays).atZone(ZoneId.systemDefault).toInstant.toEpochMilli)
}

现在,我要查找的代码可能类似于

// just a mock
when(LocalDateTime.now().minusDays(any)
    .atZone(ZoneId.systemDefault).toInstant.toEpochMilli)
    .thenReturn(1579625874972)

请注意,我知道测试中的 search.timestamp 可以更新,但这需要在每个 recencyDurationInDays 之后更新事件!!

但是在 specs2 and/or scala 中有更好更可靠的方法吗?

Edit:我必须指出,我不希望更改实现,因此 LocalDateTime 是 overridden/wrapped 和另一个 class.

powermock 这样的工具允许这样的事情。但它们是最后的解决方案,如果你必须在代码中模拟一些你无法控制的东西。

通常你会做这样的事情:

trait Clock {

  def now(): LocalDateTime  
}

class DefaultClock extends Clock {

  def now(): LocalDateTime = LocalDateTime.now()
}

然后将 Clock 实例注入到使用它的代码中。

除了模拟静态方法,您还可以传递一个实例来执行您想要的任何操作:

val simulatedNow = ... // calculate the right date for now
val clock = new Clock {
  def now() = simulatedNow
}
// inject clock
// run code and check assertion