Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mock Objects in Play[2.0]

I want to test my Play application by providing mock objects during a test. Off the top of my head, there are a few ways to go about this.

  1. Provide an alternative route files during testing
  2. Use Dependency Injection, and check for a global value at runtime

I am not sure which is more feasible, or how to go about doing them. Any insight would be greatly appreciated.

like image 964
Jacob Groundwater Avatar asked Apr 07 '12 09:04

Jacob Groundwater


2 Answers

There is a third way; create your controller as a class or a trait for testing. Here is a simple example.

Your trait + implementation:

package services

trait MyService {
  def getUser(id:String):User
}

class ConcreteService extends MyService {
  override def getUser(id:String):User = {
  //Do real stuff
  }
}

In your controller class:

package controllers

import services._

class Users(service: MyService) extends Controller {
  def show(id: String) = Action {
    val user = service.getUser(id)
    Ok(views.html.user(user))
  }
}

object Users extends controllers.Users(new ConcreteService()) {}

Now you can run some unit tests..

package test

import controllers.Users
import play.api.test._
import play.api.test.Helpers._

import org.specs2.mock.Mockito
import org.specs2.mutable.Specification

class UsersSpec extends Specification with Mockito {
  val service = mock[MyService]

  "Users controller" should {
    "list users" in {
      //Insert mocking stuff here

      val users = new Users(service)
      val result = users.show("somerandomid")(FakeRequest())
      status(result) must equalTo(OK)
    }
  }
}
like image 155
Blake Pettersson Avatar answered Oct 08 '22 18:10

Blake Pettersson


I had the same question, and experimented some options:

  • cake pattern
  • injection via implicit
  • spring

You can see the code on github here.

like image 43
Yann Simon Avatar answered Oct 08 '22 18:10

Yann Simon