Thursday, February 6, 2014

Testing Scala Futures with ScalaTest 2.0

Recently I was writing integration tests for a library that returned futures. I wanted simple synchronous tests.

Fortunately in the latest release of ScalaTest they have added something to do just that: the ScalaFutures trait

Say you have a class that returns a Future, e.g:

class ClassThatReturnsFutures() {
def goDoSomething() : Future[String] = {
future {
println("I best do this asynchronously")
"The result"
}
}
}
And you want to write a test for this and you want to wait for the future to complete. In regular code you might use a call back or a for comprehension e.g:

test("Test a asynchronous method synchronously") {
val underTest = new ClassThatReturnsFutures()
val futureResult = underTest.goDoSomething()
futureResult onComplete {
case Success(value) => value should equal("Something")
case Failure(exp) => fail(exp)
}
}

This won't work in a test as the test will finish before the future completes and the assertions are on a different thread.

ScalaFutures to the rescue! Upgrade to ScalaTest 2.0+ and mix in the ScalaFutures trait. Now you can test using whenReady:

test("Test a asynchronous method synchronously - whenReady") {
val underTest = new ClassThatReturnsFutures()
val futureResult = underTest.goDoSomething()
whenReady(futureResult) { result =>
result should equal("The result")
}
}
Or with futureValue:

test("Test a asynchronous method synchronously - futureResult") {
val underTest = new ClassThatReturnsFutures()
val futureResult = underTest.goDoSomething()
futureResult.futureValue should equal("The result")
}
Happy testing! Full source code here.

1 comment:

Unknown said...

Great post - you explained simply what other resources (and 4 hours of researching them) couldn't... which why this page is now in my bookmarks. Thanks!