In most cases, we want our unit tests to run as quickly as possible. Waiting for real time to pass can slow down our tests significantly. Effect provides a handy tool called TestClock that allows us to control time during testing. This means we can efficiently and predictably test code that involves time without having to wait for the actual time to pass.
How TestClock Works
Imagine TestClock as a wall clock that only moves forward when we adjust it manually using the TestClock.adjust and TestClock.setTime functions. The clock time does not progress on its own.
When we adjust the clock time, any effects scheduled to run at or before that time will execute. This allows us to simulate time passage in tests without waiting for real time.
Example (Simulating a Timeout with TestClock)
A key point is forking the fiber where Effect.sleep is invoked. Calls to Effect.sleep and related methods wait until the clock time matches or exceeds the scheduled time for their execution. By forking the fiber, we retain control over the clock time adjustments.
Testing Recurring Effects
Here’s an example demonstrating how to test an effect that runs at fixed intervals using the TestClock:
Example (Testing an Effect with Fixed Intervals)
In this example, we test an effect that runs at regular intervals. An unbounded queue is used to manage the effects, and we verify the following:
No effect occurs before the specified recurrence period.
An effect occurs after the recurrence period.
The effect executes exactly once.
It’s important to note that after each recurrence, the next occurrence is scheduled to happen at the appropriate time. Adjusting the clock by 60 minutes places exactly one value in the queue; adjusting by another 60 minutes adds another value.
Testing Clock
This example demonstrates how to test the behavior of the Clock using the TestClock:
Example (Simulating Time Passage with TestClock)
Testing Deferred
The TestClock also impacts asynchronous code scheduled to run after a specific time.
Example (Simulating Delayed Execution with Deferred and TestClock)