What is the better way to mock date using mockk?
r
What is the better way to mock date using mockk?
e
why would you need to do that?
1
r
to separate my test and the current time
q
Use
java.time.Clock
, if you are on the JVM.
☝️ 1
e
Or
object Time { fun now() = Instant.now() }
, for instance, and you can easily do
mockkObject(Time)
every { Time.now() } returns myTimestamp
as @Quincy mentions in the linked thread, depending your use case
r
thanks! @Emil Kantis @Quincy
q
You're welcome.
r
My current test code
Copy code
val fixedClock = Clock.fixed(
		Instant.parse("2022-01-01T23:59:59Z"),
		ZoneId.of("UTC")
	)
	mockkStatic(Clock::class)
	every { Clock.systemUTC() } returns fixedClock
	Assert.assertThat(isValidDate(), `is`(false))
q
You don't need to mock the Clock itself. Using the fixed clock gives you control over how timestamps are created. Now what you need to do is ensure the SUT takes a Clock as a parameter and uses that Clock to create timestamps.
Copy code
class Sut(private val clock: Clock) {
    fun doSomething(): OffsetDateTime {
       return OffsetDateTime.now(clock)
    }
}
For example, with the above class we can now write a test that can take control of the timestamp creation.
Copy code
fun `my_test`() {
    val now = Instant.of(1L)
    val clock = Clock.fixed(now)

    assertThat(
        Sut(clock).doSomething(),
        equalTo(OffsetDateTime.of(...))
    )
}
Something like that.
This give you the ability to let the production code use the real system clock when running in production, but within tests you can specify the behavior of the clock. And you don't need to mock anything.
r
understood, I think this is a better way to invert the dependency, thanks again
q
You're welcome again. 🙂
t
yesterday there was a similar question in #kotest, if you are using that testing framework you can also wrap your test with
withConstantNow(Instant.now())
. behind the scene it uses
mockkStatic
so it only works when in your code you do
val date = Instant.now()
and it won’t with
val date = LocalDate.now()
. you can also do
withConstantNow(LocalDate.now())
or every other time-setting instruction, though personally I still prefer to use a clock. not a big fan of static mocking in general (as much as I would actually remove it from the library)
4484 Views