在ScalaTest中将OffsetDateTime与时间戳进行比较

时间:2019-06-21 13:40:35

标签: scala timestamp 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

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

3 个答案:

答案 0 :(得分:2)

尝试将它们都转换为Long

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

答案 1 :(得分:2)

自定义平等解决方案-

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)

如果您有许多与时间相关的测试,则此方法无需每次转换。主要缺点是,显然,只有在您要与之进行比较的对象是时间戳的情况下,您才能选择性地覆盖相等性,并且如果您要进行比较,则还必须实现一个Equality[Timestamp]

答案 2 :(得分:2)

由于在许多测试中都需要自定义匹配器,所以我最终实现了该匹配器

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)