Trait/Object

zio.test.environment

TestClock

Related Docs: object TestClock | package environment

Permalink

trait TestClock extends Clock with Scheduler

TestClock makes it easy to deterministically and efficiently test effects involving the passage of time.

Instead of waiting for actual time to pass, sleep and methods implemented in terms of it schedule effects to take place at a given clock time. Users can adjust the clock time using the adjust and setTime methods, and all effects scheduled to take place on or before that time will automically be run.

For example, here is how we can test ZIO.timeout using TestClock:

import zio.ZIO
import zio.duration._
import zio.test.environment.TestClock

for {
  fiber  <- ZIO.sleep(5.minutes).timeout(1.minute).fork
  _      <- TestClock.adjust(1.minute)
  result <- fiber.join
} yield result == None

Note how we forked the fiber that sleep was invoked on. Calls to sleep and methods derived from it will semantically block until the time is set to on or after the time they are scheduled to run. If we didn't fork the fiber on which we called sleep we would never get to set the the time on the line below. Thus, a useful pattern when using TestClock is to fork the effect being tested, then adjust the clock to the desired time, and finally verify that the expected effects have been performed.

Sleep and related combinators schedule events to occur at a specified duration in the future relative to the current fiber time (e.g. 10 seconds from the current fiber time). The fiber time is backed by a FiberRef and is incremented for the duration each fiber is sleeping. Child fibers inherit the fiber time of their parent so methods that rely on repeated sleep calls work as you would expect.

For example, here is how we can test an effect that recurs with a fixed delay:

import zio.Queue
import zio.duration._
import zio.test.environment.TestClock

for {
  q <- Queue.unbounded[Unit]
  _ <- (q.offer(()).delay(60.minutes)).forever.fork
  a <- q.poll.map(_.isEmpty)
  _ <- TestClock.adjust(60.minutes)
  b <- q.take.as(true)
  c <- q.poll.map(_.isEmpty)
  _ <- TestClock.adjust(60.minutes)
  d <- q.take.as(true)
  e <- q.poll.map(_.isEmpty)
} yield a && b && c && d && e

Here we verify that no effect is performed before the recurrence period, that an effect is performed after the recurrence period, and that the effect is performed exactly once. The key thing to note here is that after each recurrence the next recurrence is scheduled to occur at the appropriate time in the future, so when we adjust the clock by 60 minutes exactly one value is placed in the queue, and when we adjust the clock by another 60 minutes exactly one more value is placed in the queue.

Linear Supertypes
Known Subclasses
Ordering
  1. Alphabetic
  2. By Inheritance
Inherited
  1. TestClock
  2. Scheduler
  3. Clock
  4. Serializable
  5. Serializable
  6. AnyRef
  7. Any
  1. Hide All
  2. Show All
Visibility
  1. Public
  2. All

Abstract Value Members

  1. abstract val clock: Service[Any]

    Permalink
    Definition Classes
    TestClock → Clock
  2. abstract val scheduler: Service[Any]

    Permalink
    Definition Classes
    TestClock → Scheduler

Concrete Value Members

  1. final def !=(arg0: Any): Boolean

    Permalink
    Definition Classes
    AnyRef → Any
  2. final def ##(): Int

    Permalink
    Definition Classes
    AnyRef → Any
  3. final def ==(arg0: Any): Boolean

    Permalink
    Definition Classes
    AnyRef → Any
  4. final def asInstanceOf[T0]: T0

    Permalink
    Definition Classes
    Any
  5. def clone(): AnyRef

    Permalink
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    @throws( ... )
  6. final def eq(arg0: AnyRef): Boolean

    Permalink
    Definition Classes
    AnyRef
  7. def equals(arg0: Any): Boolean

    Permalink
    Definition Classes
    AnyRef → Any
  8. def finalize(): Unit

    Permalink
    Attributes
    protected[java.lang]
    Definition Classes
    AnyRef
    Annotations
    @throws( classOf[java.lang.Throwable] )
  9. final def getClass(): Class[_]

    Permalink
    Definition Classes
    AnyRef → Any
  10. def hashCode(): Int

    Permalink
    Definition Classes
    AnyRef → Any
  11. final def isInstanceOf[T0]: Boolean

    Permalink
    Definition Classes
    Any
  12. final def ne(arg0: AnyRef): Boolean

    Permalink
    Definition Classes
    AnyRef
  13. final def notify(): Unit

    Permalink
    Definition Classes
    AnyRef
  14. final def notifyAll(): Unit

    Permalink
    Definition Classes
    AnyRef
  15. final def synchronized[T0](arg0: ⇒ T0): T0

    Permalink
    Definition Classes
    AnyRef
  16. def toString(): String

    Permalink
    Definition Classes
    AnyRef → Any
  17. final def wait(): Unit

    Permalink
    Definition Classes
    AnyRef
    Annotations
    @throws( ... )
  18. final def wait(arg0: Long, arg1: Int): Unit

    Permalink
    Definition Classes
    AnyRef
    Annotations
    @throws( ... )
  19. final def wait(arg0: Long): Unit

    Permalink
    Definition Classes
    AnyRef
    Annotations
    @throws( ... )

Inherited from Scheduler

Inherited from Clock

Inherited from Serializable

Inherited from Serializable

Inherited from AnyRef

Inherited from Any

Ungrouped