Reputation: 11
According to documentation, fixtures can be passed to tests like this:
def withFixture(test: OneArgTest) = {
val f = veryLengthyInitialization(test.configMap)
withFixture(test.toNoArgTest(f))
}
describe("Some test") {
it("should succeed") { f =>
f.doSomething()
// ...
}
// many other tests
// ...
}
Problem is that the initialization is run for each test, and it takes a very long time, so I would like it to run just once. Documentation suggests an alternative:
override def beforeAll(configMap: ConfigMap) {
val fOnce = veryLengthyInitialization(configMap)
// but how do I pass f to the tests?
// ugly workaround:
f = fOnce
}
var f: InitType = null
describe("Some test") {
it("should succeed") { // hack: no parameter, use var instead
f.doSomething()
// ...
}
// many other tests
// ...
}
It works, but my understanding is that null should be avoided, and it's a bit silly to rely on mutation for something as basic as this. What is the correct way to write such tests?
Upvotes: 1
Views: 2275
Reputation: 1085
I'm not sure if the below is something better:
trait DoSomething {
var f:InitType = _
def doSomething = f.doSomething
}
class MyTestSpec extends DoSomething {
override def beforeAll(configMap: ConfigMap) {
val fOnce = veryLengthyInitialization(configMap)
f = fOnce
}
it("should succeed") {
doSomething()
}
}
For any tests you need a f variable to do something, you could extend the trait and initialize it in your beforeAll methods, in addition, you could even override the doSomething in your test.
Upvotes: 0
Reputation: 6237
I don't think that there is a solution that is good in all aspects for this issue. One thing I do sometime to avoid the var
is structuring the test as follows:
class SomeTest extends Spec {
def initFixtures(): SomeFixtureType = ???
lazy val fixtures = initFixtures()
describe("Some test") {
it("should succeed") in {
fixtures.doSomething()
// ...
}
}
}
In this way I don't need to use the beforeAndAfterAll
thing, but you can if you want to guarantee that the fixtures are initialised before the test as follows:
override def beforeAll() {
super.beforeAll()
fixtures
}
It can also be handy when dealing with asynchronous initialisation since you could have something like:
class SomeTest extends Spec {
def initFixtures(): Future[SomeFixtureType] = ???
lazy val fixtures = initFixtures()
describe("Some test") {
it("should succeed") in {
whenReady(fixtures.flatMap {
f.doSomething()
// ...
}) { res => doSomeChecks(res) }
}
}
}
Having both initFixtures
and fixtures
is most useful in this case as you can have some tests re-initialise the system and act in isolation if they need to do effectful stuffs (e.g. use a database).
Upvotes: 1