ScalaTest:在同一毫秒内将 Instants 视为相等

ScalaTest: treat Instants as equal when in the same millisecond

我有一个序列化为 JSON 的案例 class,以及一个检查往返是否有效的测试案例。

隐藏在案例 class 深处的是 java.time.Instants,我将其放入 JSON 作为它们的纪元毫秒。

结果是 并且在翻译中丢失了,导致测试失败,因为时间戳现在稍微偏离了。

有没有简单的方法让Scalatest忽略差异?我只想修复测试,应用程序完全可以接受精度损失。

我们使用 Clock.instant 来知道当前时间而不是 Instant.now 来避免这个问题。所以 class 的代码应该是这样的

class MyClass(clock: Clock) {
  def getResult(): Result = {
    Result(clock.instant)
  }
}

并且在测试中,我们模拟 clock.instant 以保证我们检查的时间完全相同。

class MyClassTest {
  val customTime = Instant.now
  val clock = mock[Clock]
  clock.instant() returns customTime

  // test
  val myClass = new MyClass(clock)
  val expectedResult = Result(customTime)
  myClass.getResult ==== expectedResult
}

比较前截断到毫秒

我不确定这对您的情况是否有帮助,但以防万一,对于其他阅读的人来说:比较两个 Instant 对象的正确方法只考虑毫秒和更粗略的是将每个对象截断到毫秒精度(此处为 Java):

    Instant instant1 = Instant.parse("2018-12-14T08:25:54.232235133Z");
    Instant instant2 = Instant.parse("2018-12-14T08:25:54.232975217Z");
    if (instant1.truncatedTo(ChronoUnit.MILLIS).equals(instant2.truncatedTo(ChronoUnit.MILLIS))) {
        System.out.println("Equal to the millisecond");
    } else {
        System.out.println("Not equal to the millisecond");
    }

输出:

Equal to the millisecond

如果您知道其中一个在通过 JSON 的往返过程中已经被截断(并且您认为这是必须的要求),则不需要截断那个再次,当然。

使用只有毫秒精度的时钟

使用 Clock 进行测试通常是个好主意。它可以帮助您编写可重现的测试。你可以轻松拥有一个只计算毫秒的时钟:

    Clock c = Clock.tickMillis(ZoneOffset.UTC);
    System.out.println(c.instant());
    System.out.println(Instant.now(c));

刚才运行时输出:

2018-12-14T10:48:47.929Z
2018-12-14T10:48:47.945Z

如你所见,生成的Instant对象的秒数只有三位小数,也就是毫秒级精度,再细不过了。当你只使用 Clock 绘制 Instant 时,你传递到 tickMillis 的哪个时区并不重要。