SkyWalker
SkyWalker

Reputation: 14309

How to insert json fixture data in Play Specification tests?

I have a Scala Play 2.2.2 application and as part of my Specification tests I would like to insert some fixture data for testing preferably in json format. For the tests I use the usual in-memory H2 database. How can I accomplish this? I have searched all the documentation but there is no mention to this anywhere.

Note that I would prefer not to build my own flavor of fixture implementation via the Global. There should be a non-hacky way to this right?

Upvotes: 0

Views: 865

Answers (1)

Mikesname
Mikesname

Reputation: 8901

AFAIK there is no built-in stuff to do this, ala Rails, and it's hard to imagine what the devs could do without making Play Scala much more opinionated about the way persistence should be handled (which I'd personally consider a negative.)

I also use H2 for testing and employ plain SQL fixtures in a resource file and load them before tests using a couple of (fairly simple) helpers:

package object helpers {

  import java.io.File
  import java.sql.CallableStatement
  import org.specs2.execute.{Result, AsResult}
  import org.specs2.mutable.Around
  import org.specs2.specification.Scope
  import play.api.db.DB
  import play.api.test.FakeApplication
  import play.api.test.Helpers._

  /**
   * Load a file containing SQL statements into the DB.
   */
  private def loadSqlResource(resource: String)(implicit app: FakeApplication) = DB.withConnection { conn =>
    val file = new File(getClass.getClassLoader.getResource(resource).toURI)
    val path = file.getAbsolutePath
    val statement: CallableStatement = conn.prepareCall(s"RUNSCRIPT FROM '$path'")
    statement.execute()
    conn.commit()
  }

  /**
   * Run a spec after loading the given resource name as SQL fixtures.
   */
  abstract class WithSqlFixtures(val resource: String, val app: FakeApplication = FakeApplication()) extends Around with Scope {
    implicit def implicitApp = app
    override def around[T: AsResult](t: => T): Result = {
      running(app) {
        loadSqlResource(resource)
        AsResult.effectively(t)
      }
    }
  }
}

Then, in your actual spec you can do something like so:

package models

import helpers.WithSqlFixtures
import play.api.test.PlaySpecification

class MyModelSpec extends PlaySpecification {
  "My model" should {
    "locate items correctly" in new WithSqlFixtures("model-fixtures.sql") {
      MyModel.findAll().size must beGreaterThan(0)
    }
  }
}

Note: this specs2 stuff could probably be better.

Obviously if you really need JSON you'll have to add extra machinery to deserialise your models and persist them in the database (often in your app you'll be doing these things anyway, in which case that might be relatively trivial.)

You'll also need:

  • Some evolutions to establish your DB schema in conf/evolutions/default
  • The evolution plugin enabled, which will build your schema when the FakeApplication starts up
  • The appropriate H2 DB config

Upvotes: 2

Related Questions