在 ScalaTest 中比较 OffsetDateTime 和时间戳

Comparing OffsetDateTime to Timestamp in ScalaTest

我是 Scala 世界的新手

在我的 Scala 测试中,我有 java.time.OffsetDateTime 和 java.sql.Timestamp

offsetDateTimeValue shouldBe timestampValue

结果:

Expected :2019-06-20T16:19:57.988Z
Actual   :2019-06-20 16:19:57.988

有什么想法吗?我正在考虑实现一个自定义匹配器,但被困住了

尝试像这样将它们都转换为 Long

val expected = OffsetDateTime.parse(offsetDateTimeValue, DateTimeFormatter.ISO_OFFSET_DATE_TIME).toInstant.toEpochMilli
val actual = timestampValue.toInstant(ZoneOffset.UTC).toEpochMilli
expected shouldBe actual

自定义相等解决方案-

implicit val timeEquality : Equality[OffsetDateTime] = (a: OffsetDateTime, b: Any) => b match {
  case timestamp: Timestamp => a.toInstant == timestamp.toInstant // can also go via epoch milliseconds as per Mario's solution
  case other => a == other
}

val instant = Instant.now()
val offset = OffsetDateTime.ofInstant(instant, ZoneId.of("UTC"))
val timestamp = Timestamp.from(instant)

offset shouldEqual timestamp // test passes

使用 equal/shouldEqual 而不是 be 允许您通过实现 Equality 并将其作为隐式参数传递来自定义匹配器使用的相等性。如果不喜欢隐式的,也可以显式的传递:

val timesBeingEqual: Equality[OffsetDateTime] = ...
(offset shouldEqual timestamp)(decided by timesBeingEqual)

如果您有一堆 time-related 测试,这种方法可以避免每次都进行转换。主要的缺点是,你显然不能选择性地覆盖相等性只有在你比较的东西是时间戳的情况下,如果你想以相反的方式进行比较,你还必须实现一个Equality[Timestamp].

我最终实现了自定义匹配器,因为我在很多测试中都需要它

def beTheSameDate(right: OffsetDateTime) = DateTestMatcher(right)

case class DateTestMatcher(right: OffsetDateTime) extends Matcher[Timestamp] {
  override def apply(left: Timestamp): MatchResult = {
    val areEqual = left.toLocalDateTime == right.toLocalDateTime
    MatchResult(areEqual, "Dates are not equal", "Dates are equal")
  }

然后

timestampValue should beTheSameDate(offsetDateTimeValue)