Is there a way to access the current clock time in...
# coroutines
a
Is there a way to access the current clock time in production (
System.currentTimeMillis()
or similar…) that is compatible with the virtual clock time in
kotlinx-coroutines-test
? I found a reference to an older method that I don’t think will work since
DelayController
is deprecated, but I’m not able to find any methods to replace it.
h
Depending on your use-case you could use a TimeSource or a kotlinx-datetime Clock
a
I suppose I’m wondering more if there’s a way to get that info from the coroutineContext without referencing
TestCoroutineScheduler
in production code. I’m currently passing in a parameter to provide the time, but it’s not the most convenient to pass it through multiple functions.
h
If you only want to inject it, you could either use a "real" di framework or use coroutineContext and inject it manually with your own class and key.
a
The goal is to write a time oriented flow function that leverages the virtual clock during tests automatically. Injection is the bad/not-great solution, I was hoping for a solution that works in any coroutineContext without extra setup.
h
Could you provide your flow? You could also use
delay
in your flow BTW I mean this:
Copy code
@ExperimentalTime
class TimeSourceContext(timeSource: TimeSource): CoroutineContext.Element, TimeSource by timeSource {
  override val key: CoroutineContext.Key<TimeSourceContext> = TimeSourceContext
  companion object: CoroutineContext.Key<TimeSourceContext>
}
    
@Test
fun a() = runTest {
  withContext(TimeSourceContext(testTimeSource)) {
    val timeSource: TimeSource = coroutineContext[TimeSourceContext]!!
  }
}
a
that would be great if it were a standard context element, but I don’t want to add hidden dependencies on the context the flow is collected in.
h
Hm, I see, yeah making the context itself a TimeSource would be nice too, to run
measureTime
or getting a
TimeMark
without di.
c
A simple KotlinX.Datetime Clock implementation that uses the TestApplication context: https://gitlab.com/opensavvy/formulaide/-/blob/main/test/src/commonMain/kotlin/utils/TestClock.kt#L10 Your code:
Copy code
fun foo(clock: Clock) {
    println(clock.now())
}
Production usage (or use your favorite DI lib):
Copy code
foo(Clock.System)
Test usage:
Copy code
@Test
fun testFoo() = runTest {
    foo(testClock())
}
h
But you still need to pass the clock
145 Views