Search code examples
scalaplayframeworkscalatest

How to test asynchronous methods using scalatestplus-play


Play : 2.5.10

Scala : 2.11.11

ScalaTest plus play : "org.scalatestplus.play" %% "scalatestplus-play" % "2.0.1" % Test

How can I test service methods that return Future[Option[]]?

For example something like this definitely doesn't work, it says all tests have passed, but it simply isn't true. I change expectations to something wrong, and it still "passes":

class SomeProgressTestExampleSpec extends PlaySpec with OneAppPerSuite {
  private val progressService = 
  app.injector.instanceOf(classOf[ProgressService])

  "Retriving progress by user" must
   {
    "reflect accurate progress" in
    {
      val progressA : Future[Option[Progress]] = progressService.readByUserId(1)

      progressA.map(progressOpt =>
        progressOpt
          .foreach{
            progress =>
              progress.soFar mustBe 59
          }
      )

    }
  }
}

Solution

  • The problem is that the thread kicked off by the Future is a non-daemon thread, so won't prevent the application from exiting. The test kicks off the future, then decides it has no more work to do, so then it completes before the code is reached. The solution is to tell it to wait until the future completes. This can be done pretty simply with:

    val maxTimeToWait: Int = 1000
    val result: Option[Progress] = Await.result(progressA, maxTimeToWait)