Pages

Sunday 11 January 2015

Play and ScalaTest - testing controllers

I've started a pet project to play with different aspects of Play and Scala and today tried to decide which test library to use. The 2 main contenders are Specs2 and ScalaTest. After reading a great number of articles about both I concluded they are both offer similar functionality so either would be fine as a starting point.

To get ScalaTest running I followed the guide here:

However some tweaks were needed to get what I wanted so I'll step through it quickly here.

Add the appropriate dependency to build.sbt

"org.scalatestplus" %% "play" % "1.2.0" % "test"

Latest version numbers here: http://www.scalatest.org/plus/play/versions

Change my controller to be more testable

Instead of using a straight object for the controller having it as a trait means you can instantiate versions of it in your test, which gives you the ability to override some methods when you test it, I see this could be useful for when you want to test some things in isolation. 

However really for now I think I could just as easily just use the object directly (I've checked and the tests still work fine this way). I will follow the trait-object pattern as it seems to be recommended and hopefully will come in handy later.

Controller is:
trait QuestionsController {  
   this: Controller =>  
   def createQuestion = Action {  
      Ok(views.html.addQuestion())
   }
}  

object QuestionsController extends Controller with QuestionsController

Test the controller

The example given on the play site for unit testing shows the Ok call above just outputting text. As soon as you try to replace that with one that actually calls a view it will stop working, complaining that there is no started application.

The next page on the play site gives the answer to this, which is to mix in a fake application.

Complete test is:
import scala.concurrent.Future  
import org.scalatestplus.play._
import play.api.mvc._  
import play.api.test._  
import play.api.test.Helpers._

class QuestionsControllerSpec extends PlaySpec with OneAppPerSuite {
   class TestQuestionsController() extends Controller with QuestionsController
   "createQuestion" must {
      "direct to the create question page" in {  
         val controller = new TestQuestionsController()  
         val result: Future[Result] = controller.createQuestion().apply(FakeRequest())  
         val bodyText: String = contentAsString(result) bodyText must include("Add Question and Answer")
      }
   }


 So that's it, a simple controller test.

No comments:

Post a Comment