ScalaTest and Twitter Futures

Posted on 2015-02-02

Scala has nice abstractions for asynchronous code. However, writing tests for that code sometimes results in an ugly, unreadable mess. Fortunately, ScalaTest has built-in support for testing Futures, in addition to utilities for other types of asynchronous testing, such as polling and test-probes.


ScalaTest has a trait named Futures which defines functions such as whenReady, and other goodies like a futureValue method to help your async tests become terser. However, ScalaTest only comes with support for the standard-library Futures. To use them, mixin org.scalatest.concurrent.ScalaFutures.

If, currently like me, you’re using Twitter Futures, then you need to define your own support for them. Luckily, it is quite easy to define support for any Futures library.

Behold a TwitterFutures trait:

import com.twitter.util.{Throw, Return}
import org.scalatest.concurrent.Futures

trait TwitterFutures extends Futures {

  import scala.language.implicitConversions

  implicit def convertTwitterFuture[T](twitterFuture: com.twitter.util.Future[T]): FutureConcept[T] =
    new FutureConcept[T] {
      override def eitherValue: Option[Either[Throwable, T]] = { {
          case Return(o) => Right(o)
          case Throw(e)  => Left(e)
      override def isCanceled: Boolean = false
      override def isExpired: Boolean = false

You may also have to define an implicit PatienceConfig for your tests as the default settings will timeout after 150 milliseconds.

implicit val asyncConfig = PatienceConfig(timeout = scaled(Span(2, Seconds)))


Strangely, ScalaTest chooses to poll futures, despite both Scala and Twitter Futures coming with Await functions that handle timeouts. Using that as a starting point would have seemed more sensible to me. However, I’m not the author of a successful Scala testing library, and I’m sure that author Bill Venners had a reason. However, it is worth noting.