import org.scalatest.{ FlatSpec, Matchers, ParallelTestExecution }
import org.scalatest.concurrent.ScalaFutures
import org.apache.thrift.TApplicationException
class Test extends FlatSpec with Matchers with ScalaFutures with ParallelTestExecution {
it should "throw org.apache.thrift.TApplicationException for invalid Ids" in {
val future: Future[Response] = ThriftClient.thriftRequest
whenReady(future) {
res => {
intercept[TApplicationException] {
}
}
}
}
}
Question: How do you assert expected failures in Futures without blocking? The above doesn't work, the exception is thrown before the intercept
block.
I know this is probably a bit late, but ScalaTest provides this feature out of the box (I believe since version 2) by mixing in the ScalaFutures trait, or using it directly in your test functions. Behold!
test("some test") {
val f: Future[Something] = someObject.giveMeAFuture
ScalaFutures.whenReady(f.failed) { e =>
e shouldBe a [SomeExceptionType]
}
}
Or you can perform some other assertions in there. Basically, if your future doesn't fail like you expect, the test will fail. If it fails, but throws a different exception, the test will fail. Nice and easy! =]
cheeky edit:
You can also use this method to test anything that returns a future:
test("some test") {
val f: Future[Something] = someObject.giveMeAFuture
ScalaFutures.whenReady(f) { s =>
// run assertions against the object returned in the future
}
}
Most recent edit!
I just wanted to update this answer with more useful information based on newer versions of Scala test. The various spec traits now all have async support, so instead of extending, say, WordSpec
, you would instead extend AsyncWordSpec
, and instead of relying on the whenReady
calls as above, you would just map over your futures directly in the test.
Example:
class SomeSpec extends Async[*]Spec with Matchers {
...
test("some test") {
someObject.funcThatReturnsAFutureOfSomething map { something =>
// run assertions against the 'something' returned in the future
}
}
}