Reputation: 5521
Java 8's time API allows mocking by passing in a custom clock
in Instant.now(clock)
invocations. Similarly, LocalDateTime.now(clock)
.
I have a Deadline
object in a custom Cache implementation that indicates whether an entry is expired. I would like to be able to test this by not using sleep
method in unit test. Does classes in Scala's scala.concurrent.duration
package provide any plugin mocking capabilities?
Upvotes: 2
Views: 1012
Reputation: 1152
There doesn’t seem to be an easy way to do this using the default Deadline
class because internally it relies on the system clock which you can’t override.
One option would be for you to roll your own Deadline class that has a Clock injected to it kind of like this:
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’s Deadline class is simple enough so creating your own shouldn’t be too difficult. One downside, however, is that the smallest unit of time that Clock seems to support is milliseconds.
This aside, I’m curious as to why you chose to use Deadline
in your implementation. Other potential alternatives you can try based on my limited understanding of your use-case:
The main issue here, however, isn’t so much that testing Duration is hard, but has more to do with how Deadline was implemented. It’s the same problem that arises when testing code that uses dependency injection vs code that defines everything internally in, say, its initialization (ie. a constructor or what have you).
In terms of how people test Duration
, it's usually something that is commonly used alongside asynchronous code for timeout purposes (ie. Future, Task, IO) so people don’t often test Duration on its own. For testing asynchronous code, ScalaTest is one of several testing libs that you can use.
Upvotes: 2