Inherited from ExecutionContext
, schedules a runnable
for execution.
Inherited from ExecutionContext
, schedules a runnable
for execution.
Inherited from ExecutionContext
, reports uncaught errors.
Inherited from ExecutionContext
, reports uncaught errors.
Returns the internal state of the TestContext
, useful for testing
that certain execution conditions have been met.
Triggers execution by going through the queue of scheduled tasks and executing them all, until no tasks remain in the queue to execute.
Triggers execution by going through the queue of scheduled tasks and executing them all, until no tasks remain in the queue to execute.
Order of execution isn't guaranteed, the queued Runnable
s are
being shuffled in order to simulate the needed non-determinism
that happens with multi-threading.
implicit val ec = TestContext() val f = Future(1 + 1).flatMap(_ + 1) // Execution is momentarily suspended in TestContext assert(f.value == None) // Simulating async execution: ec.tick() assert(f.value, Some(Success(2)))
The optional parameter can be used for simulating time, to be used in
combination with cats.effect.Timer
. See the
timer method.
Example:
val ctx = TestContext() // Building a Timer[IO] from this: implicit val timer: Timer[IO] = ctx.timer[IO] // Can now simulate time val io = timer.sleep(10.seconds) *> IO(1 + 1) val f = io.unsafeToFuture() // This invariant holds true, because our IO is async assert(f.value == None) // Not yet completed, because this does not simulate time passing: ctx.tick() assert(f.value == None) // Simulating time passing: ctx.tick(10.seconds) assert(f.value == Some(Success(2))
is an optional parameter for simulating time passing;
Executes just one tick, one task, from the internal queue, useful for testing that a some runnable will definitely be executed next.
Executes just one tick, one task, from the internal queue, useful for testing that a some runnable will definitely be executed next.
Returns a boolean indicating that tasks were available and that the head of the queue has been executed, so normally you have this equivalence:
while (ec.tickOne()) {} // ... is equivalent with: ec.tick()
Note that ask extraction has a random factor, the behavior being like tick, in order to simulate non-determinism. So you can't rely on some ordering of execution if multiple tasks are waiting execution.
true
if a task was available in the internal queue, and
was executed, or false
otherwise
Derives a cats.effect.Timer
from this TestContext
, for any data
type that has a LiftIO
instance.
Derives a cats.effect.Timer
from this TestContext
, for any data
type that has a LiftIO
instance.
Example:
val ctx = TestContext() // Building a Timer[IO] from this: implicit val timer: Timer[IO] = ctx.timer[IO] // Can now simulate time val io = timer.sleep(10.seconds) *> IO(1 + 1) val f = io.unsafeToFuture() // This invariant holds true, because our IO is async assert(f.value == None) // Not yet completed, because this does not simulate time passing: ctx.tick() assert(f.value == None) // Simulating time passing: ctx.tick(10.seconds) assert(f.value == Some(Success(2))
A
scala.concurrent.ExecutionContext
implementation and a provider ofcats.effect.Timer
instances, that can simulate async boundaries and time passage, useful for testing purposes.Usage for simulating an
ExecutionContext
):Our
TestContext
can also simulate time passage, as we are able to builds acats.effect.Timer
instance for any data type that has aLiftIO
instance:We can now simulate actual time:
Simulating time makes this pretty useful for testing race conditions: