有没有一种方法可以使用规范模拟LocalDateTime时间戳

时间:2020-05-05 12:01:11

标签: scala mockito java-time specs2 localdatetime

我应该为依赖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 和/或scala中,有没有更好,更可靠的方法呢?

编辑 :我必须指出,我不希望更改实现,以使LocalDateTime被另一个类覆盖/包装。

1 个答案:

答案 0 :(得分:5)

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