Beginners Guide for Mocking in Scala

Reading Time: 3 minutes

We all must know how the unit test cases are one of the most important part of an application. If not? Then I must tell you that unit testing is one of the earliest testings which is performed on the unit of code and the earlier the defects are detected, the easier it is to fix. It reduces the difficulties of discovering errors contained in more complex pieces of the application.
So where does mocking comes into the picture? Why do we need it and how do we understand what we should mock while writing unit test cases? Answers to these questions are right below in this blog.

The idea behind mocking

There are programs that do not have any dependencies on external classes. Consider a program that has a method that prints “Hello, World”. Now, this program does not depend on any external classes. However, in real-world applications, classes have dependencies. Those dependencies are on maybe some services and those services may have dependencies on some database objects and the list goes on. The main point of writing unit test cases is to test whether our piece of code is working without interaction with the external environment, i.e if any method of other class has been called then that method should be mocked.

Consider this example:

class UserAction(loginService: LoginService) {
def displayActionsPerformed(val userId: String) {
 	val result = loginService.getListOfActionsPerformed(userId)
    if(result.size > 0){
            return SUCCESS
    }
    else {
            return FAILURE
    }
  }
}

It’s clear from the code that the class UserAction has a dependency on LoginService. Here, if we start writing unit test cases for this class, we will start by testing the displayActionPerformed method. To do that, we should be able to write test cases for this method without testing getListOfActionsPerformed. We have to assume that getListOfActionsPerformed is tested to work as it is designed. The question is how do we test displayActionsPerformed without executing getListOfActionsPerformed

That is when mocking comes into the picture. The idea behind mocking is that we will create a mock object such that it can replace the real object and will act the same as the real object. The mock object expects certain methods to be called and when that happens, it will return some expected result. In this example, we were having trouble to write unit test cases because we did not really want to execute getListOfActionsPerformed. So now, with the help of mocking, we can mock the LoginService class and create a mock object. This mock object will call the getListOfActionsPerformed method with userId parameter and it will return say, a list of actions.Now we can easily test the displayActionsPerformed method as we have the result of its dependencies.

A simple example of mocking in Scala using Mockito

Now that you all have understood the concept behind the mocking, let’s look into the Mockito library in ScalaTest.

ScalaTest’s MockitoSugar provides basic syntax sugar for Mockito. There are more choices available that we can use for mocking, such as, ScalaMock, EasyMock, and JMock. In this blog, we will be discussing the Mockito framework.

First, we need to add these two library dependencies in our build.sbt file

libraryDependencies ++= Seq ( "org.scalatest" %% "scalatest" % "3.0.1" % "test", "org.mockito" % "mockito-core" % "2.8.47" % "test" )

Now considering our previous example, let’s write test cases for it using Mockito.

Class UserActionSpec extends WordSpec with Matchers with MockitoSugar {
 val mockedLoginService = mock[LoginService]
 val userAction = new UserAction(mockedLoginService)

“UserAction#displalyActionsPerformed” should {

 “ return SUCCESS” in {
 when(mockedLoginService.getListOfActionsPerformed(any[String])) thenReturn List(“user logged in”, “user updated profile”)
 val result = userAction.displayActionsPerformed(randomUserId) 
 result shouldBe SUCCESS
  }
 }
}

Here, 

  1. We mocked our LoginService class upon which UserAction depends. 
  2. While creating an object for UserAction class we passed on the mocked parameter. 
  3. We can see how easily we can stub methods using Mockito functions: when and thenReturn
  4. Mockito also allows us to match against any argument value(as seen in the above example, how we have used any[String] as a matcher for userId parameter: when(mockedLoginService.getListOfActionsPerformed(any[String])). It also comes with regex matchers and allows us to write custom matchers.
  5. To throw exceptions with Mockito, we simply need to use the thenThrow(….) function. Here is how it can be done,
Class UserActionSpec extends WordSpec with Matchers with MockitoSugar {
val mockedLoginService = mock[LoginService]
val userAction = new UserAction(mockedLoginService)

“UserAction#dispalyActionsPerformed” should {

 “ return error” in {
 when(mockedLoginService.getListOfActionsPerformed(any[String])) thenThrow(
   new RuntimeException())
 intercept[RuntimeException]{userAction.displayActionsPerformed(randomUserId)
   }
  }
 }
}

This was all about mocking. For further details on the Mockito framework, you can read it more about it on Mockito User Guide.