Fixtures in Play! 2 for Scala

2019-03-16 14:21发布

I am trying to do some integration testing in a Play! 2 for Scala application. For this, I need to load some fixtures to have the DB in a known state before each test.

At the moment, I am just invoking a method that executes a bunch of Squeryl statements to load data. But declaring the fixtures declaratively, either with a Scala DSL or in a language like JSON or YAML is more readable and easy to mantain.

In this example of a Java application I see that fixtures are loaded from a YAML file, but the equivalent Scala app resorts to manula loading, as I am doing right now.

I have also found this project which is not very well documented, and it seems a bit more complex than I'd like - it is not even clear to me where the fixture data is actually declared.

Are there any other options to load fixtures in a Play! application?

2条回答
走好不送
2楼-- · 2019-03-16 14:47

Use Evolutions. Write a setup and teardown script for the fixtures in SQL, or use mysqldump (or equivalent for your DB) to export an existing test DB as sql.

http://www.playframework.org/documentation/1.2/evolutions

I find the most stress-free way to do testing is to set everything up in an in-memory database which means tests run fast and drive the tests from Java using JUnit. I use H2DB, but there are a few gotchas you need to watch out for. I learned these the hard way, so this should save you some time.

Play has a nice system for setting up and tearing down your application for integration testing, using running( FakeAplication() ) { .. }, and you can configure it to use an in memory database with FakeApplication(additionalConfiguration = inMemoryDatabase()) see:

http://www.playframework.org/documentation/2.0/ScalaTest

OutOfMemory errors: However, running a sizeable test fixture a few times on my machine caused OutOfMemory errors. This seems to be because the default implementation of the inMemoryDatabase() function creates a new randomly named database and doesn't clean up the old ones between test runs. This isn't necessary if you've written your evolution teardown scripts correctly, because the database will be emptied out and refilled between each test. So we overrode this behaviour to use the same database and the memory issues disappeared.

DB Dialect: Another issue is that our production database is MySQL which has a number of incompatibilities with H2DB. H2DB has compatibility modes for a number of dbs, which should reduce the number of problems you have:

http://www.h2database.com/html/features.html#compatibility

Putting this all together makes it a little unwieldy to add before each test, so I extracted it into a function:

def memDB[T](code: =>T) = 
  running( FakeApplication( additionalConfiguration = Map( 
    "db.default.driver" -> "org.h2.Driver", 
    "db.default.url"    -> "jdbc:h2:mem:test;MODE=MySQL" 
  ) ) )(code) 

You can then use it like so (specs example):

"My app" should {
  "integrate nicely" in memDB {
    .....
  }
}

Every test will start a fake application, run your fixture setup evolutions script, run the test, then tear it all down again. Good luck!

查看更多
萌系小妹纸
3楼-- · 2019-03-16 15:10

Why not use the java example in Scala? That exact code should also work without modifications in Scala...

查看更多
登录 后发表回答