Search code examples
scalaplayframeworkscalatest

Creating functional tests Scala Playframework 2.6 Macwire


I wrote some traits to use it as a base for my functional tests

This file is for creating a DB in memory (H2 + Evolutions)

BlogApiDBTest.scala

package functional.common

import play.api.db.Databases
import play.api.db.evolutions.Evolutions

trait BlogApiDBTest {

  implicit val testDatabase = Databases.inMemory(
    name = "blog_db",
    urlOptions = Map(
      "MODE" -> "MYSQL"
    ),
    config = Map(
      "logStatements" -> true
    )
  )

  org.h2.engine.Mode.getInstance("MYSQL").convertInsertNullToZero = false
  Evolutions.applyEvolutions(testDatabase)
}

Here I am overriding some injected components for testing purposes

BlogApiComponentsTest.scala

package functional.common

import common.BlogApiComponents
import org.scalatestplus.play.components.WithApplicationComponents
import play.api.{BuiltInComponents, Configuration}

trait BlogApiComponentsTest extends WithApplicationComponents with BlogApiDBTest {

  override def components: BuiltInComponents = new BlogApiComponents(context) {
    override lazy val configuration: Configuration = context.initialConfiguration
    override lazy val blogDatabase = testDatabase
  }

}

This is the base class for my functional tests

BlogApiOneServerPerTestWithComponents.scala

package functional.common

import org.scalatestplus.play.PlaySpec
import org.scalatestplus.play.components.{OneServerPerTestWithComponents}

trait BlogApiOneServerPerTestWithComponents extends PlaySpec with OneServerPerTestWithComponents with BlogApiComponentsTest {

}

Finally the test I am trying to execute

PostControllerSpec.scala

package functional.controllers

import functional.common.BlogApiOneServerPerTestWithComponents
import org.scalatest.concurrent.{IntegrationPatience, ScalaFutures}
import play.api.mvc.{Results}
import play.api.test.{FakeRequest, Helpers}


import play.api.test.Helpers.{GET, route}

class PostControllerSpec extends BlogApiOneServerPerTestWithComponents
  with Results
  with ScalaFutures
  with IntegrationPatience {

  "Server query should" should {
    "provide an Application" in {
      val Some(result) = route(app, FakeRequest(GET, "/posts"))
      Helpers.contentAsString(result) must be("success!")
    }
  }

}

Then I get

blog-api/test/functional/controllers/PostControllerSpec.scala:18:31: Cannot write an instance of play.api.mvc.AnyContentAsEmpty.type to HTTP response. Try to define a Writeable[play.api.mvc.AnyContentAsEmpty.type]

Here is the code


Solution

  • Adding the following import should make it work:

    import play.api.test.Helpers._
    

    Looking at the signature of route

    def route[T](app: Application, req: Request[T])(implicit w: Writeable[T]): Option[Future[Result]]
    

    we see it expects an implicit w: Writeable[T]. The above import will provide it via Writables