μ€λν
09/07/2023, 2:09 PMjw
09/07/2023, 2:14 PMμ€λν
09/07/2023, 2:25 PMclass TestClock : Clock {
private var testInstant: Instant? = null
override fun now(): Instant {
return testInstant ?: Clock.System.now()
}
fun fixAt(time: LocalDateTime) {
testInstant = time.toInstant(TimeZone.UTC)
}
fun reset() {
testInstant = null
}
}
you mean using fake clock instance for test like this?jw
09/07/2023, 2:25 PMjw
09/07/2023, 2:30 PMMustafa Ozhan
09/08/2023, 8:02 AMfun nowAsInstant() = Clock.System.now()
fun nowAsLong() = nowAsInstant().toEpochMilliseconds()ptsiogas
09/08/2023, 8:40 AMKlitos Kyriacou
09/08/2023, 8:49 AMClock instance as a parameter to any method (or any class constructor) that needs the time. Pass it Clock.System in production, and TestClock in unit tests, where you define TestClock.now() to return a test value. Something analogous to java.time.Clock.systemUTC() vs java.time.Clock.fixed().CLOVIS
09/08/2023, 9:46 AMThat's really bad: it means you can't switch the clock to fake times. You're going to regret this a lot when you need to debug something that only happens on a very specific dateCopy codefun nowAsInstant() = Clock.System.now()
ptsiogas
09/08/2023, 9:54 AMmilliseconds: Long as an input, even now date should be an input. With that way you wonβt have the need for Clock.Mustafa Ozhan
09/08/2023, 10:03 AMThatβs really bad: it means you canβt switch the clock to fake times.It will happen only if you use these directly in a class, but you can have interfaces to abstract away these implementations as a result you can always mock them. ie.
every { appStorage.premiumEndDate }
.returns(nowAsLong() + 1.seconds.inWholeMilliseconds)CLOVIS
09/08/2023, 10:17 AMClock ?Javier
09/08/2023, 10:19 AMMustafa Ozhan
09/08/2023, 11:05 AMμ€λν
09/10/2023, 1:14 AMJoffrey
09/11/2023, 12:16 AMμ€λν
09/11/2023, 12:26 AMjw
09/11/2023, 12:27 AMjw
09/11/2023, 12:27 AMμ€λν
09/11/2023, 12:41 AMjw
09/11/2023, 12:42 AMμ€λν
09/11/2023, 12:45 AMCLOVIS
09/11/2023, 7:47 AMFakes should be shared, possibly even tested themselvesIf anyone's interested, here's a codebase that does that: https://gitlab.com/opensavvy/formulaide The domain layer (
:core) contains data classes and service declarations as interfaces. The :fake module contains in-memory implementations of all these interfaces. The :test module contains test suites that check the validity of an implementation. All implementations of the interface (:fake which is in-memory, :mongo which handles persistence, :remote for client-server communication, etc) are all tested using the same test suite. I'm experimenting with having UI tests also use the same suite.
No matter what technologies you use, the only real requirement for doing that is to be able to declare tests programmatically. In that project, I'm hacking around through JUnit5 test inheritance and Kotlin/JS's test runners internals⦠I'm working on releasing that test harness as a standalone library, but any other test framework with this feature (e.g. Kotest) would work as well.