https://kotlinlang.org logo
#mockk
Title
# mockk
r

Recca Chao

09/29/2021, 2:16 PM
What is the better way to mock date using mockk?
e

Emil Kantis

09/29/2021, 2:18 PM
why would you need to do that?
1
r

Recca Chao

09/29/2021, 2:23 PM
to separate my test and the current time
q

Quincy

09/29/2021, 2:32 PM
Use
java.time.Clock
, if you are on the JVM.
☝️ 1
e

Emil Kantis

09/29/2021, 2:47 PM
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

Recca Chao

09/29/2021, 2:56 PM
thanks! @Emil Kantis @Quincy
q

Quincy

09/29/2021, 3:05 PM
You're welcome.
r

Recca Chao

09/29/2021, 4:11 PM
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

Quincy

09/29/2021, 4:13 PM
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

Recca Chao

09/29/2021, 4:22 PM
understood, I think this is a better way to invert the dependency, thanks again
q

Quincy

09/29/2021, 4:50 PM
You're welcome again. 🙂
t

thanksforallthefish

09/30/2021, 6:00 AM
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)
2320 Views