首页 > 解决方案 > 为什么对对象的 val 的 scala 测试断言会抛出 NullPointerException?

问题描述

在测试 Scala 代码时,我在断言来自对象的值时遇到了一个奇怪的 NPE。

这是重现该问题的最少代码:

主/斯卡拉/Playground.scala:

object Playground extends App {
  val greeting = "Hello Scala"
  println(greeting)
}

测试/scala/PlaygroundSpec.scala:

import org.scalatest.wordspec._

class PlaygroundSpec extends AnyWordSpec {
  "The playground code" should {
    "say hello" in {
      assert(Playground.greeting.contains("Hello")) // Throws NPE because greeting is null. How???
    }
  }
}

示例程序运行良好并打印“hello Scala”,但测试在断言行抛出 NullPointerException,因为greetingis null.

如果它greetingnull用字符串常量初始化的呢?

注意:添加lazyval声明中使其工作并且测试通过。

标签: scalascalatest

解决方案


你可以这样定义Playground

object Playground /*extends App*/ {
  val greeting = "Hello Scala"
  println(greeting)
}

或者你可以这样定义greeting

object Playground extends App {
  lazy val greeting = "Hello Scala"
  println(greeting)
}

Scala 2.x 的这种奇怪行为的解释是App延迟加载的特性。这在过去对许多其他人来说一直是个问题。Scala 3 将改变这一点。

对于 Scala 2,最安全的选择是将对象引用移到 的主体之外App,例如:

class Playground {
  val greeting = "Hello Scala"
  println(greeting)
}

object Playground extends App {
  new Playground
}

推荐阅读