Squeryl testing with specs2: gotchas

A quick start guide to using squeryl with specs2 for unit testing.

In the absence of a detailed quick start guide to testing Squeryl projects with specs2, I’ve ended writing up some information for anyone else getting started with combining both projects. After quite a bit of hair pulling, I got some guidance on doing so from @etorreborre.

Avoid implicit clashes

As it turns out Squeryl and specs2 have a number of name clashes. You can avoid the implicits clash by using the `>>` operator and other similar abbreviations provided by specs2 when you run into them. I initially had no idea they existed and spent a fair bit of time trying to fix this implicit resolution issue whilst grumbling loudly on Twitter:

"Schema stored in database should" >> {
"allow creation of new entries" >> {
val datum = data.insert(new Datum(0, Some(1),Some(""), Some("ftp.example.org"), Some("username"), Some("password"), Some(new java.util.Date)))
datum.id must_== 1
}
}
view raw schema.scala hosted with ❤ by GitHub

Sequential execution or concurrent execution

If you have issues with examples being executed concurrently you can try to use the `sequential` argument at the beginning of the specification:

class DatabaseSpec extends Specification { def is = sequential ^
"This is a specification to check the database schema"
view raw database.scala hosted with ❤ by GitHub

Other bits of advice I got included pointing out that sometimes it is smarter to attach the database session to the current thread, so that you can still have your examples being executed concurrently. Also, if you create a `Before` context object, you need to `apply` it to your example body, but the easiest thing to do is to use the BeforeExample trait in that case.

Here’s an example unit test to get you started:

package appname.unit
import org.specs2.mutable._
import org.specs2.specification.BeforeExample
import org.specs2.specification._
import org.squeryl._
import adapters.H2Adapter
import PrimitiveTypeMode._
import appname.schema._
import DBSchema._
class DatabaseUnitSpec extends Specification with BeforeExample{
def before = initialize
"Schema stored in database should" >> {
"allow creation of new entries" >> {
transaction {
val datum = data.insert(new Datum(0, Some(1),Some(""), Some("ftp.example.org"), Some("username"), Some("password"), Some(new java.util.Date)))
datum.id must_== 1
}
}
"allow retrieval of entries" >> {
transaction {
data.insert(new Datum(0, Some(1),Some(""), Some("ftp.example.org"), Some("username"), Some("password"), Some(new java.util.Date)))
val datum = data.where(a => a.id === 1).single
datum.id must_== 1
}
}
}
// Initialization & tear-down functions
def initialize = {
println("Setting up data.")
Class.forName("org.h2.Driver")
SessionFactory.concreteFactory = Some(()=>
Session.create(
java.sql.DriverManager.getConnection("jdbc:h2:~/example", "sa", ""),
new H2Adapter)
)
inTransaction {
drop
create
printDdl
}
}
}
view raw sample.scala hosted with ❤ by GitHub