Pledge
is a value that can be completed later, much like a
Scala Promise
, but pure, to be used in describing laws that
require the observation of side effects.
A scala.concurrent.ExecutionContext
implementation and a provider
of cats.effect.Timer
instances, that can simulate async boundaries
and time passage, useful for testing purposes.
A scala.concurrent.ExecutionContext
implementation and a provider
of cats.effect.Timer
instances, that can simulate async boundaries
and time passage, useful for testing purposes.
Usage for simulating an ExecutionContext
):
implicit val ec = TestContext() ec.execute(new Runnable { def run() = println("task1") }) ex.execute(new Runnable { def run() = { println("outer") ec.execute(new Runnable { def run() = println("inner") }) } }) // Nothing executes until `tick` gets called ec.tick() // Testing the resulting state assert(ec.state.tasks.isEmpty) assert(ec.state.lastReportedFailure == None)
Our TestContext
can also simulate time passage, as we are able
to builds a cats.effect.Timer
instance for any data type that
has a LiftIO
instance:
val ctx = TestContext() val timer: Timer[IO] = ctx.timer[IO]
We can now simulate actual 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))
Simulating time makes this pretty useful for testing race conditions:
val never = IO.async[Int](_ => {}) val timeoutError = new TimeoutException val timeout = timer.sleep(10.seconds) *> IO.raiseError[Int](timeoutError) val pair = (never, timeout).parMapN(_ + _) // Not yet ctx.tick() assert(f.value == None) // Not yet ctx.tick(5.seconds) assert(f.value == None) // Good to go: ctx.tick(5.seconds) assert(f.value, Some(Failure(timeoutError)))
Defines instances for Future
and for IO
, meant for law testing
by means of TestContext.
Defines instances for Future
and for IO
, meant for law testing
by means of TestContext.
The TestContext interpreter is used here for simulating asynchronous execution.
Pledge
is a value that can be completed later, much like a ScalaPromise
, but pure, to be used in describing laws that require the observation of side effects.The internal implementation effectively wraps a Scala
Promise
, so it has the same contract:Example: