$shibayu36->blog;

株式会社はてなでエンジニアをしています。プログラミングや読書のことなどについて書いています。

PlayFrameworkでのcontrollerのテストのやり方メモ

PlayFrameworkでcontrollerのテストどうやるんだろうといろいろ試してみたのでメモ。Play 2.6.3を使っている。

基本的なやり方

play-scala-seed.g8というのに、基本的なControllerとそのテスト方法について書かれているので、それを真似れば良い。

Play 2.6ではControllerは@InjectでControllerComponentsを渡す形式が一般的なので、stubControllerComponents()で得られるテスト用のControllerComponentsを渡せばテストできるっぽい。あとはFakeRequestでテストしたいRequestを作り、いろいろとテストしていくだけ。

自分でControllerのテストの基底クラスを作る

とりあえず真似れば良いのだけど、それだとあまり理解できないので、自分好みのテストのやり方になるようにControllerのテストの基底クラスを作ってみた。PlaySpecの実装を見ながら作った。

test/test/ControllerSpec.scala

package test

import org.scalatest.FunSpec
import org.scalatestplus.play.guice.GuiceOneAppPerTest

abstract class ControllerSpec extends FunSpec with GuiceOneAppPerTest with org.scalatest.Matchers

PlaySpecとの違いは

  • 普通にdescribeとかitとかを使ってテストをしたかったので、WordSpecではなくてFunSpecをmixinした
  • mustBeじゃなくてshouldBeを使いたかったのでMustMatchersではなくてMatchersをmixinした
  • あとはアプリケーションを起動できるように(?)、GuiceOneAppPerTestをmixinした
    • GuiceOneAppPerTestの役割はまだちゃんと理解は出来ていない

これでこの基底クラスを使って以下のようにテストできる。

test/controllers/HomeControllerSpec.scala

package controllers

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

class HomeControllerSpec extends test.ControllerSpec {
  describe("HomeController GET") {
    it("render the index page from a new instance of controller") {
      val controller = new HomeController(stubControllerComponents())
      val home = controller.index().apply(FakeRequest(GET, "/"))

      status(home) shouldBe OK
      contentType(home) shouldBe Some("text/html")
      contentAsString(home) should include ("Welcome to Play")
    }
  }
}