Testing Scala application using Play framework and Mockito

12 July 2017

In this example the controller class Product Controller fetches data from an external service called DataService. Since we can't call real APIs during Test we need to mock DataService and return mock data instead. Similar to Java, in Scala there are also many options for using mock libraries. One popular mock library is Mockito, in this example we use it to return a fake instance and inject it into the application in test using GuiceApplicationBuilder, we also leverage play framework's testing support capability. The test reads from a JSON file Source called "sample_offer_list.json", builds the json object representation and validates the fields values.

Injected JSON Mock data

{
   "list":[
      {
         "id":"1",
         "upc":"upc1",
         "name":"prod 1",
         "partyName":"pty 1",
         "semanticName":"sem1",
         "mainImageFileUrl":"http://localhost:5555/assets/images/image-placeholder.png",
         "partyImageFileUrl":"http://localhost:5555/assets/images/best-buy-logo.png",
         "price":55.55,
         "productCategory":"laptops",
         "rating":4.5,
         "numReviews":100
      },
      {
         "id":"2",
         "upc":"upc2",
         "name":"prod 2",
         "partyName":"pty 2",
         "semanticName":"sem2",
         "mainImageFileUrl":"http://localhost:5555/assets/images/image-placeholder.png",
         "partyImageFileUrl":"http://localhost:5555/assets/images/best-buy-logo.png",
         "price":445.55,
         "productCategory":"laptops",
         "rating":2.55,
         "numReviews":200
      },
      {
         "id":"3",
         "upc":"upc3",
         "name":"prod 3",
         "partyName":"pty 3",
         "semanticName":"sem3",
         "mainImageFileUrl":"http://localhost:5555/assets/images/image-placeholder.png",
         "partyImageFileUrl":"http://localhost:5555/assets/images/best-buy-logo.png",
         "price":445.55,
         "productCategory":"laptops",
         "rating":3.55,
         "numReviews":300
      }
   ],
   "summary":{
      "page":1,
      "pageCount":1,
      "totalCount":3
   }
}

Sample Test

import scala.io.Source
import org.junit.runner.RunWith
import org.scalatest.
import org.scalatest.mockito.MockitoSugar
import org.scalatestplus.play.
import org.scalatestplus.play.PlaySpec
import play.api.inject.bind
import play.api.inject.guice.GuiceApplicationBuilder
import play.api.inject.guice.GuiceableModule
import play.api.libs.json.
import play.api.libs.json.Json
import product.model.OfferDetail
import product.model.OfferList
import product.services.market.walmart.WalmartRepository
import org.mockito.Mockito.
import org.mockito.Matchers.
import play.api.test.Helpers.
import play.api.test.CSRFTokenHelper._
import play.api.test.WithApplication
import play.api.test.FakeRequest
import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global
import org.scalatest.junit.JUnitRunner

@RunWith(classOf[JUnitRunner]) class ProductControllerSpec extends PlaySpec with MockitoSugar { / MOCK data / val productList = Json.parse(Source.fromFile("conf/app/sample_offer.json").getLines.mkString).as[OfferList]
val myMock = mock[DataRepository] when(myMock.search(any[Map[String,String]])) thenReturn Future.successful(Some(productList))
val appMock = new GuiceApplicationBuilder() .overrides(bind[DataRepository].toInstance(myMock)) .build "index" in new WithApplication(appMock) { val request = FakeRequest(GET, "/products").withHeaders(HOST -> "localhost:9000") val response = route(app, request).get val json = contentAsJson(response) val elem0 = (json \ "list")(0) status(response) mustBe OK (elem0 \ "id").as[String] mustBe "1" (elem0 \ "name").as[String] mustBe "prod 1" } }

comments powered by Disqus