cats.effect.laws.util

Type members

Classlikes

final class TestContext extends ExecutionContext

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)))
Companion
object
object TestContext
Companion
class

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.

Companion
object
Companion
class