scala - 单元测试期间 Scala Deadline 的模拟时间

标签 scala time

Java 8 的时间 API 允许通过在 Instant.now(clock) 中传入自定义时钟来进行模拟。调用。同样,LocalDateTime.now(clock) .

我在自定义缓存实现中有一个 Deadline 对象,用于指示条目是否过期。我希望能够通过在单元测试中不使用 sleep 方法来测试这一点。 Scala 的 scala.concurrent.duration 包中的类是否提供任何插件模拟功能?

最佳答案

似乎没有一种简单的方法可以使用默认的 Deadline 类来执行此操作,因为它在内部依赖于您无法覆盖的系统时钟。

一种选择是您推出自己的 Deadline 类,其中注入(inject)了一个 Clock,如下所示:

case class Deadline(clock: Clock, time: FiniteDuration) {
  def +(other: FiniteDuration): Deadline = copy(time = time + other)
  def -(other: FiniteDuration): Deadline = copy(clock = clock, time = time - other)
  def -(other: Deadline): FiniteDuration = time - other.time
  def timeLeft: FiniteDuration = this - Deadline.now
  def isOverdue: Boolean = (time.toMillis - clock.millis()) < 0
  def hasTimeLeft: Boolean = !isOverdue
}

object Deadline {
  def now: Deadline = {
    val clock = Clock.systemDefaultZone()
    Deadline(clock, Duration(clock.millis(), TimeUnit.MILLISECONDS))
  }
}

Scala 的 Deadline 类非常简单,因此创建自己的 Deadline 类应该不会太困难。然而,一个缺点是 Clock 似乎支持的最小时间单位是毫秒。

除此之外,我很好奇您为什么选择在实现中使用Deadline。根据我对您的用例的有限理解,您可以尝试其他潜在的替代方案:

  • 为缓存中的每个条目分配一个过期时间,并在下次访问时检查它是否应该失效/删除
  • 如果缓存支持异步性,您可以使用某种 IO/任务数据类型根据条目的过期时间安排删除条目。然而,随着缓存的增长,这种方法可能无法很好地扩展
  • 使用支持 TTL 的第三方缓存库。一个例子是 Play 框架中的缓存 API,它作为一个独立的库提供,您无需携带框架的其余部分即可使用。我相信 Google Guava 库也提供了一些不同的缓存实现

然而,这里的主要问题并不是测试 Duration 很困难,而是与 Deadline 的实现方式有关。当测试使用依赖注入(inject)的代码与在内部定义所有内容的代码(例如,其初始化(即构造函数或其他什么))时,也会出现同样的问题。

就人们如何测试 Duration 而言,它通常与异步代码一起用于超时目的(即 Future、Task、IO),因此人们不会经常在其上测试 Duration自己的。对于测试异步代码,ScalaTest 是您可以使用的几个测试库之一。

关于scala - 单元测试期间 Scala Deadline 的模拟时间,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50955230/

相关文章:

scala - 如何使 scala 集合包含唯一元素? ("unique"定义)

javascript - 如何从剩余时间中减去时间?

validation - Scalaz 验证,验证内部值

java - 'jvm-1。 8' is not a valid choice for '-目标'

php - 检查当前时间是否在两个时间之间,是否有重叠天数

python - 如何让 python 代码在时间 y 和 z 之间每隔 x 分钟循环一次?

c - C 中的 time(NULL) 是什么?

datetime - 时间上的奇怪行为。Go 中的 Parse 函数

scala - 如何使用反射实例化 Scala 对象

scala - 在 SPARK 中使用 elasticsearch-spark 从 Elasticsearch 读取数据时如何转换类型