trait Futures extends PatienceConfiguration
Trait that facilitates testing with futures.
This trait defines a FutureConcept
trait that can be used to implicitly wrap
different kinds of futures, thereby providing a uniform testing API for futures.
The three ways this trait enables you to test futures are:
1. Invoking isReadyWithin
, to assert that a future is ready within a a specified time period.
Here's an example:
assert(result.isReadyWithin(100 millis))
2. Invoking futureValue
, to obtain a futures result within a specified or implicit time period,
like this:
assert(result.futureValue === 7) // Or, if you expect the future to fail: assert(result.failed.futureValue.isInstanceOf[ArithmeticException])
3. Passing the future to whenReady
, and performing assertions on the result value passed
to the given function, as in:
whenReady(result) { s =>
s should be ("hello")
}
The whenReady
construct periodically inspects the passed
future, until it is either ready or the configured timeout has been surpassed. If the future becomes
ready before the timeout, whenReady
passes the future's value to the specified function.
To make whenReady
more broadly applicable, the type of future it accepts is a FutureConcept[T]
,
where T
is the type of value promised by the future. Passing a future to whenReady
requires
an implicit conversion from the type of future you wish to pass (the modeled type) to
FutureConcept[T]
. Subtrait JavaFutures
provides an implicit conversion from
java.util.concurrent.Future[T]
to FutureConcept[T]
.
For example, the following invocation of whenReady
would succeed (not throw an exception):
import org.scalatest._ import Matchers._ import concurrent.Futures._ import java.util.concurrent._ val exec = Executors.newSingleThreadExecutor val task = new Callable[String] { def call() = { Thread.sleep(50); "hi" } } whenReady(exec.submit(task)) { s => s should be ("hi") }
However, because the default timeout is 150 milliseconds, the following invocation of
whenReady
would ultimately produce a TestFailedException
:
val task = new Callable[String] { def call() = { Thread.sleep(500); "hi" } } whenReady(exec.submit(task)) { s => s should be ("hi") }
Assuming the default configuration parameters, a timeout
of 150 milliseconds and an
interval
of 15 milliseconds,
were passed implicitly to whenReady
, the detail message of the thrown
TestFailedException
would look like:
The future passed to whenReady was never ready, so whenReady timed out. Queried 95 times, sleeping 10 milliseconds between each query.
Configuration of whenReady
The whenReady
methods of this trait can be flexibly configured.
The two configuration parameters for whenReady
along with their
default values and meanings are described in the following table:
Configuration Parameter | Default Value | Meaning |
---|---|---|
timeout | scaled(150 milliseconds) |
the maximum amount of time to allow unsuccessful queries before giving up and throwing TestFailedException
|
interval | scaled(15 milliseconds) | the amount of time to sleep between each query |
The default values of both timeout and interval are passed to the scaled
method, inherited
from ScaledTimeSpans
, so that the defaults can be scaled up
or down together with other scaled time spans. See the documentation for trait ScaledTimeSpans
for more information.
The whenReady
methods of trait Futures
each take a PatienceConfig
object as an implicit parameter. This object provides values for the two configuration parameters. Trait
Futures
provides an implicit val
named defaultPatience
with each
configuration parameter set to its default value.
If you want to set one or more configuration parameters to a different value for all invocations of
whenReady
in a suite you can override this
val (or hide it, for example, if you are importing the members of the Futures
companion object rather
than mixing in the trait). For example, if
you always want the default timeout
to be 2 seconds and the default interval
to be 5 milliseconds, you
can override defaultPatience
, like this:
implicit override val defaultPatience = PatienceConfig(timeout = Span(2, Seconds), interval = Span(5, Millis))
Or, hide it by declaring a variable of the same name in whatever scope you want the changed values to be in effect:
implicit val defaultPatience = PatienceConfig(timeout = Span(2, Seconds), interval = Span(5, Millis))
In addition to taking a PatienceConfig
object as an implicit parameter, the whenReady
methods of trait
Futures
include overloaded forms that take one or two PatienceConfigParam
objects that you can use to override the values provided by the implicit PatienceConfig
for a single whenReady
invocation. For example, if you want to set timeout
to 6 seconds for just one particular whenReady
invocation,
you can do so like this:
whenReady (exec.submit(task), timeout(Span(6, Seconds))) { s => s should be ("hi") }
This invocation of eventually
will use 6000 for timeout
and whatever value is specified by the
implicitly passed PatienceConfig
object for the interval
configuration parameter.
If you want to set both configuration parameters in this way, just list them separated by commas:
whenReady (exec.submit(task), timeout(Span(6, Seconds)), interval(Span(500, Millis))) { s => s should be ("hi") }
You can also import or mix in the members of SpanSugar
if
you want a more concise DSL for expressing time spans:
whenReady (exec.submit(task), timeout(6 seconds), interval(500 millis)) { s => s should be ("hi") }
Note: The whenReady
construct was in part inspired by the whenDelivered
matcher of the
BlueEyes project, a lightweight, asynchronous web framework for Scala.
- Source
- Futures.scala
- Alphabetic
- By Inheritance
- Futures
- PatienceConfiguration
- AbstractPatienceConfiguration
- ScaledTimeSpans
- AnyRef
- Any
- Hide All
- Show All
- Public
- All
Type Members
-
final
case class
PatienceConfig
(timeout: Span = scaled(Span(150, Millis)), interval: Span = scaled(Span(15, Millis))) extends Product with Serializable
Configuration object for asynchronous constructs, such as those provided by traits
Eventually
andWaiters
.Configuration object for asynchronous constructs, such as those provided by traits
Eventually
andWaiters
.The default values for the parameters are:
Configuration Parameter Default Value timeout
scaled(150 milliseconds)
interval
scaled(15 milliseconds)
- timeout
the maximum amount of time to wait for an asynchronous operation to complete before giving up and throwing
TestFailedException
.- interval
the amount of time to sleep between each check of the status of an asynchronous operation when polling
- Definition Classes
- AbstractPatienceConfiguration
-
trait
FutureConcept
[T] extends AnyRef
Concept trait for futures, instances of which are passed to the
whenReady
methods of traitFutures
.
Value Members
-
final
def
!=(arg0: Any): Boolean
- Definition Classes
- AnyRef → Any
-
final
def
##(): Int
- Definition Classes
- AnyRef → Any
-
final
def
==(arg0: Any): Boolean
- Definition Classes
- AnyRef → Any
-
final
def
asInstanceOf[T0]: T0
- Definition Classes
- Any
-
def
clone(): AnyRef
- Attributes
- protected[java.lang]
- Definition Classes
- AnyRef
- Annotations
- @throws( ... )
-
final
def
eq(arg0: AnyRef): Boolean
- Definition Classes
- AnyRef
-
def
equals(arg0: Any): Boolean
- Definition Classes
- AnyRef → Any
-
def
finalize(): Unit
- Attributes
- protected[java.lang]
- Definition Classes
- AnyRef
- Annotations
- @throws( classOf[java.lang.Throwable] )
-
final
def
getClass(): Class[_]
- Definition Classes
- AnyRef → Any
-
def
hashCode(): Int
- Definition Classes
- AnyRef → Any
-
def
interval(value: Span): Interval
Returns an
Interval
configuration parameter containing the passed value, which specifies the amount of time to sleep after a retry.Returns an
Interval
configuration parameter containing the passed value, which specifies the amount of time to sleep after a retry.- Definition Classes
- PatienceConfiguration
-
final
def
isInstanceOf[T0]: Boolean
- Definition Classes
- Any
-
final
def
ne(arg0: AnyRef): Boolean
- Definition Classes
- AnyRef
-
final
def
notify(): Unit
- Definition Classes
- AnyRef
-
final
def
notifyAll(): Unit
- Definition Classes
- AnyRef
-
implicit
def
patienceConfig: PatienceConfig
Implicit
PatienceConfig
value providing default configuration values.Implicit
PatienceConfig
value providing default configuration values.To change the default configuration, override or hide this
def
with another implicitPatienceConfig
containing your desired default configuration values.- Definition Classes
- PatienceConfiguration → AbstractPatienceConfiguration
-
final
def
scaled(span: Span): Span
Scales the passed
Span
by theDouble
factor returned byspanScaleFactor
.Scales the passed
Span
by theDouble
factor returned byspanScaleFactor
.The
Span
is scaled by invoking itsscaledBy
method, thus this method has the same behavior: The value returned byspanScaleFactor
can be any positive number or zero, including a fractional number. A number greater than one will scale theSpan
up to a larger value. A fractional number will scale it down to a smaller value. A factor of 1.0 will cause the exact sameSpan
to be returned. A factor of zero will causeSpan.ZeroLength
to be returned. If overflow occurs,Span.Max
will be returned. If underflow occurs,Span.ZeroLength
will be returned.- Definition Classes
- ScaledTimeSpans
- Exceptions thrown
IllegalArgumentException
if the value returned fromspanScaleFactor
is less than zero
-
def
spanScaleFactor: Double
The factor by which the
scaled
method will scaleSpan
s.The factor by which the
scaled
method will scaleSpan
s.The default implementation of this method will return the span scale factor that was specified for the run, or 1.0 if no factor was specified. For example, you can specify a span scale factor when invoking ScalaTest via the command line by passing a
-F
argument toRunner
.- Definition Classes
- ScaledTimeSpans
-
final
def
synchronized[T0](arg0: ⇒ T0): T0
- Definition Classes
- AnyRef
-
def
timeout(value: Span): Timeout
Returns a
Timeout
configuration parameter containing the passed value, which specifies the maximum amount to wait for an asynchronous operation to complete.Returns a
Timeout
configuration parameter containing the passed value, which specifies the maximum amount to wait for an asynchronous operation to complete.- Definition Classes
- PatienceConfiguration
-
def
toString(): String
- Definition Classes
- AnyRef → Any
-
final
def
wait(): Unit
- Definition Classes
- AnyRef
- Annotations
- @throws( ... )
-
final
def
wait(arg0: Long, arg1: Int): Unit
- Definition Classes
- AnyRef
- Annotations
- @throws( ... )
-
final
def
wait(arg0: Long): Unit
- Definition Classes
- AnyRef
- Annotations
- @throws( ... )
-
final
def
whenReady[T, U](future: FutureConcept[T])(fun: (T) ⇒ U)(implicit config: PatienceConfig, pos: Position): U
Queries the passed future repeatedly until it either is ready, or a configured maximum amount of time has passed, sleeping a configured interval between attempts; and when ready, passes the future's value to the passed function.
Queries the passed future repeatedly until it either is ready, or a configured maximum amount of time has passed, sleeping a configured interval between attempts; and when ready, passes the future's value to the passed function.
The maximum amount of time in milliseconds to tolerate unsuccessful attempts before giving up is configured by the
timeout
field of thePatienceConfig
passed implicitly as the last parameter. The interval to sleep between attempts is configured by theinterval
field of thePatienceConfig
passed implicitly as the last parameter.If the
eitherValue
method of the underlying Scala future returns ascala.Some
containing ascala.util.Failure
containing ajava.util.concurrent.ExecutionException
, and this exception contains a non-null
cause, that cause will be included in theTestFailedException
as its cause. TheExecutionException
will be be included as theTestFailedException
's cause only if theExecutionException
's cause isnull
.- future
the future to query
- fun
the function to which pass the future's value when it is ready
- config
an
PatienceConfig
object containingtimeout
andinterval
parameters that are unused by this method- returns
the result of invoking the
fun
parameter
-
final
def
whenReady[T, U](future: FutureConcept[T], interval: Interval)(fun: (T) ⇒ U)(implicit config: PatienceConfig, pos: Position): U
Queries the passed future repeatedly until it either is ready, or a configured maximum amount of time has passed, sleeping a configured interval between attempts; and when ready, passes the future's value to the passed function.
Queries the passed future repeatedly until it either is ready, or a configured maximum amount of time has passed, sleeping a configured interval between attempts; and when ready, passes the future's value to the passed function.
The maximum amount of time in milliseconds to tolerate unsuccessful attempts before giving up is configured by the
timeout
field of thePatienceConfig
passed implicitly as the last parameter. The interval to sleep between attempts is configured by the value contained in the passedinterval
parameter.- future
the future to query
- interval
the
Interval
configuration parameter- fun
the function to which pass the future's value when it is ready
- config
an
PatienceConfig
object containingtimeout
andinterval
parameters that are unused by this method- returns
the result of invoking the
fun
parameter
-
final
def
whenReady[T, U](future: FutureConcept[T], timeout: Timeout)(fun: (T) ⇒ U)(implicit config: PatienceConfig, pos: Position): U
Queries the passed future repeatedly until it either is ready, or a configured maximum amount of time has passed, sleeping a configured interval between attempts; and when ready, passes the future's value to the passed function.
Queries the passed future repeatedly until it either is ready, or a configured maximum amount of time has passed, sleeping a configured interval between attempts; and when ready, passes the future's value to the passed function.
The maximum amount of time in milliseconds to tolerate unsuccessful queries before giving up and throwing
TestFailedException
is configured by the value contained in the passedtimeout
parameter. The interval to sleep between attempts is configured by theinterval
field of thePatienceConfig
passed implicitly as the last parameter.If the
eitherValue
method of the underlying Scala future returns ascala.Some
containing ascala.util.Failure
containing ajava.util.concurrent.ExecutionException
, and this exception contains a non-null
cause, that cause will be included in theTestFailedException
as its cause. TheExecutionException
will be be included as theTestFailedException
's cause only if theExecutionException
's cause isnull
.- future
the future to query
- timeout
the
Timeout
configuration parameter- fun
the function to which pass the future's value when it is ready
- config
an
PatienceConfig
object containingtimeout
andinterval
parameters that are unused by this method- returns
the result of invoking the
fun
parameter
-
final
def
whenReady[T, U](future: FutureConcept[T], timeout: Timeout, interval: Interval)(fun: (T) ⇒ U)(implicit config: PatienceConfig, pos: Position): U
Queries the passed future repeatedly until it either is ready, or a configured maximum amount of time has passed, sleeping a configured interval between attempts; and when ready, passes the future's value to the passed function.
Queries the passed future repeatedly until it either is ready, or a configured maximum amount of time has passed, sleeping a configured interval between attempts; and when ready, passes the future's value to the passed function.
The maximum amount of time to tolerate unsuccessful queries before giving up and throwing
TestFailedException
is configured by the value contained in the passedtimeout
parameter. The interval to sleep between attempts is configured by the value contained in the passedinterval
parameter.If the
eitherValue
method of the underlying Scala future returns ascala.Some
containing ascala.util.Failure
containing ajava.util.concurrent.ExecutionException
, and this exception contains a non-null
cause, that cause will be included in theTestFailedException
as its cause. TheExecutionException
will be be included as theTestFailedException
's cause only if theExecutionException
's cause isnull
.- future
the future to query
- timeout
the
Timeout
configuration parameter- interval
the
Interval
configuration parameter- fun
the function to which pass the future's value when it is ready
- config
an
PatienceConfig
object containingtimeout
andinterval
parameters that are unused by this method- returns
the result of invoking the
fun
parameter