Java 8的时间API通过在Instant.now(clock)
调用中传入自定义clock
来进行模拟。同样,LocalDateTime.now(clock)
。
我在自定义缓存实现中有一个Deadline
对象,该对象指示条目是否过期。我希望能够通过在单元测试中不使用sleep
方法来对此进行测试。 Scala的scala.concurrent.duration
包中的类是否提供任何插件模拟功能?
答案 0 :(得分:1)
使用默认的Deadline
类似乎并不是一种简单的方法,因为它在内部依赖于您无法覆盖的系统时钟。
一个选择是让您滚动自己的Deadline类,并为其注入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类非常简单,因此创建自己的类应该不太困难。但是,缺点之一是Clock似乎支持的最小时间单位是毫秒。
此外,我很好奇您为什么选择在实现中使用Deadline
。根据我对用例的有限了解,您可以尝试其他可能的选择:
然而,这里的主要问题并不是很难测试持续时间,而是更多有关“截止日期”的实施方式。测试使用依赖注入的代码与在内部定义所有内容的代码(例如,构造函数或您拥有的东西)进行测试时,会出现相同的问题。
就人们如何测试Duration
而言,它通常与异步代码一起用于超时(例如,Future,Task,IO),因此人们不必经常单独测试Duration。对于测试异步代码,ScalaTest是可以使用的多个测试库之一。