Skip to content

Time

class Time

Time control helper. See time.

Constructors

Time

@ExperimentalCoroutinesApi
constructor(environment: TestEnvironment)

Properties

clock

Creates a Clock that follows the virtual time in this test.

Example
test("Pass the time to an external service") {
    val service = SomeExternalService(time.clock)
}

See also

now

Access the current virtual time within this test, as an Instant.

Example
test("Using the virtual time") {
    val initial = time.now

    // …do something…
    delay(5000)

    check(time.now == initial + 5000)
}

For the specific use-case of measuring elapsed time, see Time.source.

See also

  • clock: To pass the time to another system.

nowMillis

Accesses the current time inside the test, in milliseconds.

Example
test("Using the virtual time") {
    val initial = time.nowMillis

    // …do something…
    delay(5000)

    check(time.nowMillis == initial + 5000)
}

For the specific use-case of measuring elapsed time, see Time.source.

See also

scheduler

Accessor for the underlying TestCoroutineScheduler, which controls the current time.

Delay-skipping behavior is implemented by this dispatcher. Only delay calls within this dispatcher can be skipped and can advance the virtual time. That is, using code like withContext(Dispatchers.IO) { … } overrides the dispatcher and disables delay-skipping for the entire block.

Sometimes, you may need to instantiate a service within your tests, that you want to internally use delay-skipping. In these situations, you may need to pass the scheduler:

test("Test a cron service") {
   val cron = CronService(coroutineContext = time.scheduler)
   var witness = false

   cron.runIn(2.minutes) { witness = true }

   check(witness == false)
   delay(2.minutes)
   check(witness == true)
}

If the service expects a CoroutineScope, see foregroundScope and backgroundScope instead.

source

Access a time source which can be used to measure elapsed time, as controlled with time.

Example
test("Measure time") {
    val start = time.source.markNow()
    // …
    val duration = start.elapsedNow()
}

Functions

advanceBy

Advances the current time by delay.

Example
test("Hello world") {
    val start = time.source.markNow()
    time.advanceBy(2.minutes)
    val elapsed = start.elapsedNow()

    assertEquals(2.minutes, elapsed)
}
Stability warning

The KotlinX.Coroutines team is considering removing this functionality. Learn more in #3919.

advanceByMillis

Advances the current time by delay.

Stability warning

The KotlinX.Coroutines team is considering removing this functionality. Learn more in #3919.

advanceUntilIdle

Runs all enqueued tasks in the specified order, advancing the virtual time as needed until there are no more scheduled tasks.

This is similar to delay(Long.MAX_VALUE), except it leaves the virtual time on whenever the last task was scheduled.

Example
test("Execute subtasks") {
    launch {
        delay(1000)
        println("A")

        launch {
            delay(3000)
            println("B")
        }
    }

    launch {
        delay(2000)
        println("C")
    }

    time.advanceUntilIdle()
    assertEquals(4000, time.nowMillis)
}
Background tasks

This method advances time until all the last foreground tasks's scheduled time. There may be background tasks that are scheduled for later.

Stability warning

The KotlinX.Coroutines team is considering removing this functionality. Learn more in #3919.

delayUntil

Delays until the virtual time reaches instant, executing all enqueued tasks in order.

delayUntil is useful to artificially trigger time-dependent algorithms. To set the initial time at the start of the test, use set.

Delays until the virtual time reaches isoString, formatted as an ISO 8601 timestamp, executing all enqueued tasks in order.

delayUntil is useful to artificially trigger time-dependent algorithms. To set the initial time at the start of the test, use set.

See also

  • set: Set the current time

  • now: Access the current time

runCurrent

Runs all enqueued tasks at this moment in the virtual time.

Example
test("Execute task") {
    launchInBackground {
        delay(1000)
        println("Hello world!")
    }

    launchInBackground {
        delay(2000)
        println("Will never be printed")
    }

    time.advanceByMillis(1000)
    time.runCurrent() // prints "Hello world!"
}
Stability warning

The KotlinX.Coroutines team is considering removing this functionality. Learn more in #3919.

set

@ExperimentalCoroutinesApi
suspend fun Time.set(instant: Instant)

Advances the virtual time until it reaches instant.

Comparison with delayUntil

This function is identical in behavior to delayUntil. It exists because tests often read better when using it to set the initial date:

test("Some test") {
    // Given:
    time.set(Instant.parse("2024-02-13T21:32:41Z"))

    // When:
    // …
    delayUntil(Instant.parse("2024-02-13T21:35:01Z"))
    // …

    // Then:
    // …
}

We recommend using set to set the initial date at the very start of a test, and using delayUntil inside the test logic.

It is not possible to set the time to a date in the past.

@ExperimentalCoroutinesApi
suspend fun Time.set(isoString: String)

Advances the virtual time until it reaches isoString, formatted as an ISO 8601 timestamp.

It is not possible to set the time to a date in the past.

Example
test("Everything should behave the same on December 31st") {
    time.set("2022-12-31T23:37:00Z")

    // …
}
Comparison with delayUntil

This function is identical in behavior to delayUntil. It exists because tests often read better when using it to set the initial date:

test("Some test") {
    // Given:
    time.set("2024-02-13T21:32:41Z")

    // When:
    // …
    delayUntil("2024-02-13T21:35:01Z")
    // …

    // Then:
    // …
}

We recommend using set to set the initial date at the very start of a test, and using delayUntil inside the test logic.

See also

  • now: Access the current time

  • delay: Wait for some duration

  • delayUntil: Wait for a specific time