When you run a specification, a java.util.concurrent.ExecutorService is used to execute examples concurrently. You can access this ExecutorService to execute scalaz.concurrent.Futures and it can also be wrapped into a scala.concurrent.ExecutionContext to create scala.concurrent.Futures.
A Scala Future needs an implicit ExecutionContext to be created. You can reuse scala.concurrent.ExecutionContext.Implicits.global):
class MyFutureSpec extends Specification { def is = s2"""
Let's check this scala future ${ implicit ec: ExecutionContext =>
Await.result(Future(1), Duration.Inf) must_== 1
}
"""
}
// in a mutable specification
class MyMutableFutureSpec extends mutable.Specification {
"Let's check this scala future" >> { implicit ec: ExecutionContext =>
Await.result(Future(1), Duration.Inf) must_== 1
}
}
You can also use
class MyFutureSpec extends Specification { def is = s2"""
Let's check this scala future ${ implicit ee: ExecutionEnv =>
Await.result(Future(1), Duration.Inf) must_== 1
}
"""
}
This works thanks to an implicit conversion between ExecutionEnv and ExecutionContext provided by the org.specs2.execute.ImplicitExecutionContextFromExecutionEnv trait (this can be deactivated by mixing-in the NoImplicitExecutionContextFromExecutionEnv trait). It is actually better to use an ExecutionEnv anyway because it is required when you want to create Future matchers (see the “Future” tab).
A Scalaz Future needs an implicit ExecutorService to evaluate values asynchronously. You can require an ExecutorService in your examples like this:
class MyFutureSpec extends Specification { def is = s2"""
Let's check this scalaz future ${ implicit es: ExecutorService =>
scalaz.concurrent.Future(1).run must_== 1
}
"""
}
And, similarly to the section above, you can get an implicit ExecutorService from an ExecutionEnv:
class MyFutureSpec extends Specification { def is = s2"""
Let's check this scalaz future ${ implicit ee: ExecutionEnv =>
scalaz.concurrent.Future(1).run must_== 1
}
"""
}
You will also need a ScheduledExecutorService if you want to evaluate a Scalaz Future using the timed method (from Scalaz > 7.1):
class MyFutureSpec extends Specification { def is = s2"""
Let's check this scalaz future ${ implicit ee: ExecutionEnv =>
implicit val ses = ee.scheduledExecutorService
scalaz.concurrent.Future(1).timed(3.seconds).run.toOption must beSome(1)
}
"""
}
Future Matchers (see the “Future” tab) require an implicit ExecutionEnv. This environment is used to access:
timeFactor when awaiting for Scala FuturesscheduledExecutorService and the `timeFactor when attempting Scalaz FuturesThe terminate matcher (see the “Termination” tab in the optional Matchers section) also needs an ExecutionEnv to run a piece of code and periodically check if it has terminated or not:
s2"""
this code must be fast enough ${ implicit ee: ExecutionEnv =>
Thread.sleep(100) must terminate(retries = 1, sleep = 60.millis)
}
"""
Passing an implicit ExecutionEnv for each example can be tedious. An ExecutionEnv can be injected to the specification to make it available to all examples at once:
case class MyFutureSpec(implicit ee: ExecutionEnv) extends Specification { def is = s2"""
Let's check this scala future ${
Future(1) must be_==(1).await
}
"""
}
Another possibility is to mix-in the org.specs2.specification.ExecutionEnvironment trait to your specification:
class MyFutureSpec extends Specification with ExecutionEnvironment { def is(implicit ee: ExecutionEnv) = s2"""
Let's check this scala future ${
Future(1) must be_==(1).await
}
"""
}
// in a mutable specification
class MyMutableFutureSpec extends mutable.Specification with specification.mutable.ExecutionEnvironment { def is(implicit ee: ExecutionEnv) = {
"Let's check this scala future" >> {
Future(1) must be_==(1).await
}
}}