in my test class I want to do something before all the tests begin, so I did something like this:
class ApplicationSpec extends FreeSpec with OneServerPerSuite with BeforeAndAfterAll {
override protected def beforeAll(): Unit = {
doSomething()
}
"Application Test" - {
"first test" in {
...
}
}
}
but I get an error:
Exception encountered when invoking run on a nested suite - There is no started application java.lang.RuntimeException: There is no started application
it only works if i try to use doSomething() inside the tests...
how can i fix this?
thanks!
I am assuming doSomething()
performs some operation that is dependent on application state.
Try this:
class ApplicationSpec extends FreeSpec with BeforeAndAfterAll with OneServerPerSuite{
override protected def beforeAll(): Unit = {
doSomething()
}
"Application Test" - {
"first test" in {
...
}
}
}
The problem is you are possibly mixin linearization in wrong order
.
By mixin
OneSerPerSuite before BeforeAndAfterAll, the order in which the super.run()
is called is reversed, leading to beforeAll()
being called before Application start.
From the git repo of the two projects:
//BeforeAndAfterAll
abstract override def run(testName: Option[String], args: Args): Status = {
if (!args.runTestInNewInstance && (expectedTestCount(args.filter) > 0 || invokeBeforeAllAndAfterAllEvenIfNoTestsAreExpected))
beforeAll()
val (runStatus, thrownException) =
try {
(super.run(testName, args), None)
}
catch {
case e: Exception => (FailedStatus, Some(e))
}
...
}
//OneServerPerSuite
abstract override def run(testName: Option[String], args: Args): Status = {
val testServer = TestServer(port, app)
testServer.start()
try {
val newConfigMap = args.configMap + ("org.scalatestplus.play.app" -> app) + ("org.scalatestplus.play.port" -> port)
val newArgs = args.copy(configMap = newConfigMap)
val status = super.run(testName, newArgs)
status.whenCompleted { _ => testServer.stop() }
status
} catch { // In case the suite aborts, ensure the server is stopped
case ex: Throwable =>
testServer.stop()
throw ex
}
}
So by putting the OneServerPerSuite
trait in the end, it will first initialize the application
, then call super.run()
which will call the run
method inside BeforeAndAfterAll
which will execute beforeAll()
and then invoke super.run()
of FreeSpec
which will execute the tests.