Scala: Prettifying test builders with package object
We have several different test builders in our code base which look roughly like this:
case class FooBuilder(bar : String, baz : String) {
def build = new Foo(bar, baz)
}
In our tests we originally used them like this:
class FooPageTest extends Specs with ShouldMatchers {
it("should let us load a foo") {
when(databaseHas(FooBuilder(bar = "Bar", baz = "Bazz")))
// and so on...
}
}
This works well but we wanted our tests to only contain domain language and no implementation details.
We therefore started pulling out methods like so:
class FooPageTest extends Specs with ShouldMatchers {
it("should let us load a foo") {
when(databaseHas(aFooWithBarAndBaz("Bar", "Bazza")))
// and so on...
}
def aFooWithBarAndBaz(bar:String, baz;String) = FooBuilder(bar = bar, baz = baz)
}
This was fine to start with but we eventually ended up with 10-12 different variations oh how Foo could be constructed, negating the value that the builder pattern provides.
Instead what we can do is use of an alias of FooBuilder to achieve something equally readable:
package object TestSugar {
val aFooWith = FooBuilder
}
We can then use aFooWith like so:
import TestSugar._
class FooPageTest extends Specs with ShouldMatchers {
it("should let us load a foo") {
when(databaseHas(aFooWith(bar = "Bar", baz = "Bazza")))
// and so on...
}
}
We could also achieve that by renaming FooBuilder to aFooWith but that makes it much less discoverable whereas this solution lets us achieve both goals.
The package object approach isn’t really needed - we could easily put those vals onto an Object or Class but they don’t really seem to belong to any which is why we’ve gone for this approach.
About the author
I'm currently working on short form content at ClickHouse. I publish short 5 minute videos showing how to solve data problems on YouTube @LearnDataWithMark. I previously worked on graph analytics at Neo4j, where I also co-authored the O'Reilly Graph Algorithms Book with Amy Hodler.