I think you're slightly mixing concepts - but that's not 100% your fault.
The thing is, Future in Scala is a bit non-orthogonal concept - that it is, it represents not only the notion of delayed execution, but also a notion of failure.
Because of this, in most cases it doesn't make much sense to wrap the Future into the Try, or vice versa - unless one wants to explicitly separate the notion of failure from the notion of asynchrony.
In other words, the following combinations are sort of weird, but still has their use:
Try[Future[_]] - future already captures failures. However, makes sense if you have a (bad-behaving) library method that normally returns a Future, but may throw on a "synchronous" path:
def futureReciprocal(i: Int): Float = {
val reciprocal = 1 / i // Division by zero is intentional
Future.successful(reciprocal)
}
futureReciprocal(0) // throws
Try(futureReciprocal(0)) // Failure(DivisionByZero(...))
... but this is basically a workaround to fix poorly implemented function
Future[Try[_]] - sometimes useful to separate the "business" error (represented by Future.success(Failure(...))) from "infrastructure" failure (represented by Future.failed(...)). On a side - this is especially useful with akka-streams, which tend to treat failed futures as "fatal" to the stream.
In your case, what you want to do is to assert on the result of the future. To do so, you have at least two options, actually.
- Block till the future is completed and check the outcome - this is usually done with
scala.concurrent.Await:
// writing this without the compiler, might mix up namespaces a bit
import scala.concurrent.Await
import scala.concurrent.duration.DurationInt
val future = fooClient.fetchBar(...)
val futureResult: Try[_] = Await.result(future, 1.second)
futureResult match { case Success(_) => ??? ; case Failure(exc) => ???; }
- Use some test framework that supports working with futures - e.g. scalatest:
class YourTest extends FlatSpec with ScalaFutures {
"fetchBar should return failed future" in {
val future: Future[XYZ] = fooClient.fetchBar(...)
// whenReady comes from the ScalaFutures trait
whenReady(future) { result => result shouldBe XYZ } // asserting on the successful future result
whenReady(future.failed) { exc => exc shoulBe a[RuntimeException] } // asserting on an exception in the failed future
}
}
Try[Future[T]]doesn't make much sense, special because a Future already catch failures. I would recommend you to take a look to the documentation. - Luis Miguel Mejía Suárez