I am supposedly contributing to the integration tests of a library which relies on specs
with the underlying implementation written in Scala
. The testing is more bind towards the stream of events flowing with some timestamp
attribute.
The following stub is the part of the actual implementation
private def eligibleForRecentPost(optionalPost: Option[SearchEntity]): Boolean = {
optionalSearch.map(search => search.timestamp)
.exists(searchTime => searchTime >= LocalDateTime.now()
.minusDays(recencyDurationInDays).atZone(ZoneId.systemDefault).toInstant.toEpochMilli)
}
Now, the code that I would look for might be something like
// just a mock
when(LocalDateTime.now().minusDays(any)
.atZone(ZoneId.systemDefault).toInstant.toEpochMilli)
.thenReturn(1579625874972)
Note, I am aware that the search.timestamp in the test could be updated, but that would require updating the events after every recencyDurationInDays
!!
But is there a better and reliable way to do this in specs2 and/or scala?
Edit: I must mention that I am not looking forward to changing the implementation such that the LocalDateTime
is overridden/wrapped with another class.
There are tools like powermock which allows such things. But they are last resort solution, if you have to mock something in code that you have no control over.
Normally you would instead do something like:
trait Clock {
def now(): LocalDateTime
}
class DefaultClock extends Clock {
def now(): LocalDateTime = LocalDateTime.now()
}
and then inject Clock
instance into the code that uses it.
Instead of mocking static method you could just pass an instance that does whatever you wanted:
val simulatedNow = ... // calculate the right date for now
val clock = new Clock {
def now() = simulatedNow
}
// inject clock
// run code and check assertion