ScalaTest 111: How to use Mock objects with ScalaTest

Problem: You want to use a mock object framework in your ScalaTest tests, such as Mockito.

Solution

ScalaTest offers support for the following mock testing frameworks:

Because the support for each framework is similar, let’s take a look at using Mockito.

Before starting, imagine that you have a login web service for your application, and rather than call the real web service during your tests, you just want to mock one up.

In your application you have “login service” code in a file named src/main/scala/tests/LoginService.scala, which looks like this:

package tests

// a very simple User class
case class User(name: String)

// a LoginService must have a 'login' method
trait LoginService {
  def login(name: String, password: String): Option[User]
}

// the code for our real/live LoginService
class RealLoginService extends LoginService {
  // implementation here ...
}

Notice that there’s a LoginService trait, and the RealLoginService implements that trait. By following this pattern, you can use Mockito to “mock” your LoginService trait in your unit tests.

The following code shows how to create and use a mock LoginService using Mockito and ScalaTest:

package tests

import org.scalatest.FunSuite
import org.scalatest.BeforeAndAfter
import org.scalatest.mockito.MockitoSugar
import org.mockito.Mockito._

class LoginServiceTests extends FunSuite with BeforeAndAfter with MockitoSugar {

  test ("test login service") {

    // (1) init
    val service = mock[LoginService]

    // (2) setup: when someone logs in as "johndoe", the service should work;
    //            when they try to log in as "joehacker", it should fail.
    when(service.login("johndoe", "secret")).thenReturn(Some(User("johndoe")))
    when(service.login("joehacker", "secret")).thenReturn(None)

    // (3) access the service
    val johndoe = service.login("johndoe", "secret")
    val joehacker = service.login("joehacker", "secret")

    // (4) verify the results
    assert(johndoe.get == User("johndoe"))
    assert(joehacker == None)

  }

}

Here’s a quick description of the code:

  1. In the “init” step, you create a mock version of the LoginService. Notice that this mocks a a trait that doesn’t have an implementation. Because you can do this, you don’t have to write a separate MockLoginService class, which is nice. (You also don’t have to access Test or Production versions of the “real” login service, which would slow down your unit tests.)
  2. In the “setup” portion of the code, you work with Mockito to define how the mock LoginService should respond when it’s given two sets of data. When “johndoe” logs in, the mock login service should return a Some(User(“johndoe”)) instance, and when “joehacker” attempts to log in, it should return a None.
  3. In the “access” portion of the code, you write the code just like you would normally in your application. You call the LoginService instance with some data, and get objects in return.
  4. In the “verify” portion of the code, you verify that you received the data you expected from your login service.

In more real-world tests, you’d do things slightly differently. First, you’d use a more robust User class. Second, you’d take the objects that are received from the LoginService and attempt to do more things with them. There isn’t much value in testing a mock LoginService by itself, but because this mock service lets you test the next steps in your application, a mock service becomes a very useful thing.

This example is just intended to get you started in the right direction. The important part of the test is that you got a User object back from the LoginService, just as though you had called a real, live, production login service.

Note: The MockitoSugar import statement apparently changed since I originally wrote this article. I updated the source code here, and I hope it now includes the correct import. See the comment in the Comments section below for the old and new import statement.

Steps to using Mockito

To use Mockito like this in a ScalaTest project, the first step is to include the Mockito JAR file in your project. Assuming you’re using SBT, either add the Mockito JAR file to your project’s lib directory, or add Mockito as a dependency in your build.sbt file. With ScalaTest 1.9.1, this is the correct line to add to your build.sbt file:

libraryDependencies += "org.mockito" % "mockito-all" % "1.8.4"

The next step is to add the necessary imports to your unit test classes. These were shown in the example, and are repeated here:

import org.scalatest.mockito.MockitoSugar
import org.mockito.Mockito._

Next, mix the MockitoSugar trait into your test class:

class PizzaTests extends FunSuite with BeforeAndAfter with MockitoSugar {

Once you have these configuration steps out of the way, you can begin creating mock objects in your ScalaTest tests with Mockito.

See Also

There are many more ways to use Mockito and other mock object frameworks in your ScalaTest tests. These links will help you get started: