【问题标题】:Is there a way to mock LocalDateTime timestamp using specs有没有办法使用规范来模拟 LocalDateTime 时间戳
【发布时间】:2020-08-20 02:02:59
【问题描述】:

据说我正在为一个依赖于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 被另一个类覆盖/包装。

【问题讨论】:

  • 很遗憾您不能或不会修改实现。对于任何可以的人,请允许我建议答案在这个问题中:Writing and testing convenience methods using Java 8 Date/Time classes。和/或here
  • @OleV.V.确实。在发布问题之前,我已经浏览了 StackOverflow 上的所有此类链接,这也是明确编辑的原因。我很想理想地修改实现,但这并不总是实际上可能的。 :)

标签: scala mockito java-time specs2 localdatetime


【解决方案1】:

有像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

【讨论】:

  • 这也是更新实际代码的建议吗?如果是这样,我的错,我必须在问题中提到,这是我不期待的一个方向。
  • 那么你唯一的希望就是powermock。正常的模拟不会让你模拟静态方法。即使使用 powermock,这也是脆弱的,因为这实际上需要 JVM 修改现有类的字节码,而不是像普通模拟那样创建代理。有关更多详细信息,请参阅此答案stackoverflow.com/questions/10583202/…
  • Java 有自己的时钟实现来解决这类问题,Cats 也有,这是正确的编码方式,如果你想乱搞,那就做任何事情,但这是正确的方法跨度>
猜你喜欢
  • 2022-07-15
  • 2016-11-30
  • 1970-01-01
  • 2020-07-21
  • 2016-10-06
  • 1970-01-01
  • 1970-01-01
  • 2019-06-12
  • 1970-01-01
相关资源
最近更新 更多