I would be grateful if someone could explain to me why the following causes problems. I've created a small example to demonstrate the issue:
I have a project I'm building with sbt, build.sbt being as follows:
lazy val root = (project in file(".")).
settings(
name := "Test",
version := "1.0.0",
scalaVersion := "2.11.5",
libraryDependencies += "org.scalatest" %% "scalatest" % "2.2.4" % Test
)
and Test.scala in src/main/scala:
object Test extends App
{
private val map = Map(1 -> 2)
def access = map(1)
println(access)
}
and TestSpec.scala (using scalatest) in src/test/scala:
import org.scalatest.FlatSpec
class TestSpec extends FlatSpec
{
"A Test" should "allow access to the map" in
{
assert(Test.access == 2)
}
}
If I sbt run
then '2' gets printed out as expected. If I sbt test
then I get a NullPointerException and the test fails:
[info] TestSpec:
[info] A Test
[info] - should allow access to the map *** FAILED ***
[info] java.lang.NullPointerException:
[info] at Test$.access(Test.scala:4)
[info] at TestSpec$$anonfun$1.apply$mcV$sp(TestSpec.scala:7)
etc.
This is because map is null when TestSpec accesses it. I can fix this by changing the map to be a lazy val or a def, but I'd like to know a bit more detail about what's going on with the initialisation order here and how I can avoid this kind of thing in the future. I don't have any problems if I try to access it with another source file in src\main\scala, and I'd like to avoid changing the definitions of my variables in this way to fix this kind of issue.
Thanks