vikash dat
vikash dat

Reputation: 1514

How does play framework unit testing controller methods

According to the documentation, to unit test controllers, I need to make my controllers a trait, then override the methods

http://www.playframework.com/documentation/2.2.0/ScalaTest

However, if I override my methods, i'm effectively not testing my logic. I may not be grasping something, but I don't see how this unit tests my controller's methods?

Upvotes: 2

Views: 2919

Answers (3)

driangle
driangle

Reputation: 11779

The problem with the example in the link you've provided is that it doesn't really show the benefit of having your controller implementation within a trait. In other words, the same example could've been accomplished without using traits by just testing the controller companion object directly.

The benefit of having your controller logic be within a trait is that it allows you to override dependencies that controller may have with mock implementations/values.

For example, you could define a controller as:

trait MyController extends Controller {
   lazy val someService : SomeService = SomeServiceImpl
}
object MyController extends MyController

And in your test, you can override the service dependency:

val controller = new MyController {
  override lazy val someService = mockService
} 

Upvotes: 2

Sergey Kravchenya
Sergey Kravchenya

Reputation: 324

Here is my simple example of how you can check if some url is available

import org.specs2.mutable._
import org.specs2.runner._
import org.junit.runner._

import play.api.test._
import play.api.test.Helpers._

/**
 * Set of tests which are just hitting urls and check
 * if response code 200 returned
 */
@RunWith(classOf[JUnitRunner])
class ActionsSanityCheck extends Specification {

  def checkIfUrlAccessible(url: String): Unit = {
    val appRoute = route(FakeRequest(GET, url)).get

    status(appRoute) must equalTo(OK)
    contentType(appRoute) must beSome.which(_ == "text/html")
  }

  "Application" should {

    "send 404 on a bad request" in new WithApplication {
      route(FakeRequest(GET, "/nowhere")) must beNone
    }

    "render the index page" in new WithApplication {checkIfUrlAccessible("/")}
    "render team page" in new WithApplication {checkIfUrlAccessible("/team")}
  }
}

Upvotes: 0

Jim Jeffries
Jim Jeffries

Reputation: 10081

As mentioned in the link the controllers in play are scala objects not classes so can't be instantiated like a class. By making it a trait instead you can make a test class which you can instantiate in your test. No need to override the methods though.

To use the example from the link, here we are making a TestController class that has the same behaviour as the ExampleController object. We don't need to override our index method as we inherit the behaviour from the trait.

Main file

trait ExampleController {
  this: Controller =>

  def index() = Action {
    Ok("ok")
  }
}

object ExampleController extends Controller with ExampleController

Test File

object ExampleControllerSpec extends PlaySpecification with Results {

  class TestController() extends Controller with ExampleController

  "Example Page#index" should {
    "should be valid" in {
      val controller = new TestController()
      val result: Future[SimpleResult] = controller.index().apply(FakeRequest())
      val bodyText: String = contentAsString(result)
      bodyText must be equalTo "ok"
    }
  }
}

Upvotes: 0

Related Questions