Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Async Test

Testing asynchronous code in Scala, especially when working with futures, requires a testing framework that can handle asynchronous results. ScalaTest provides excellent support for writing tests for asynchronous operations through its AsyncTestSuite traits. Let's demonstrate how to write an asynchronous test for a hypothetical asynchronous version of the Calculator that returns Future[Int] results.

Step 1: Implement the Async Calculator

First, we'll define an asynchronous Calculator object. For demonstration purposes, we'll make the add method asynchronous, returning a Future[Int].

import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global

object AsyncCalculator {
  def add(a: Int, b: Int): Future[Int] = Future {
    // Simulate a computation that takes time
    Thread.sleep(100)
    a + b
  }
}

Step 2: Set Up ScalaTest Dependency

Ensure you have ScalaTest added to your build.sbt file:

libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.9" % Test

Step 3: Write an Asynchronous Test

ScalaTest's AsyncFunSuite is designed for testing asynchronous code. It allows tests to return Future[Assertion]. Here's how you can test the asynchronous add method of our AsyncCalculator.

import org.scalatest.funsuite.AsyncFunSuite
import org.scalatest.matchers.should.Matchers

class AsyncCalculatorSpec extends AsyncFunSuite with Matchers {

  test("AsyncCalculator.add should correctly add two numbers") {
    val sumFuture = AsyncCalculator.add(1, 2) // This returns a Future[Int]
    sumFuture.map(sum => sum should be (3)) // The assertion is wrapped in a map and returns a Future[Assertion]
  }

}

Step 4: Running the Test

Execute your asynchronous tests by running:

sbt test

Understanding the Test Code

  • AsyncFunSuite: This suite is specifically designed for asynchronous code, allowing tests to return Future[Assertion] directly. ScalaTest handles the future and correctly reports the test result once the future completes.
  • Future.map: The assertion is made within the map of the Future, which transforms the result of the future (Int) into a test assertion. The entire expression returns a Future[Assertion], which AsyncFunSuite awaits.