在 scalatest 中导入隐式方法

Importing implicit methods in scalatest

我很难理解为什么隐式导入在 scalatest 中不能像我期望的那样工作。简化的失败示例(使用 spark,但我也可以使用我的自定义 class 使其失败)如下所示:

class FailingSpec extends FlatSpec with Matchers with MySparkContext {

    val testSqlctx = sqlctx
    import sqlctx.implicits._

    "sql context implicts" should "work" in {
        val failingDf = Seq(ID(1)).toDS.toDF
    }
}

MySparkContext 特性在 beforeAllafterAll 中创建和销毁 spark 上下文,并使 sqlctx 可用(已经必须将其重新分配给局部变量以导入隐式是一个难题,但也许在不同的时间)。 .toDS.toDF 是从 sqlctx.implicits 导入的隐式方法。 运行 测试结果为 java.lang.NullPointerException

如果我将导入移动到测试块中,一切正常:

class WorkingSpec extends FlatSpec with Matchers with MySparkContext {

    "sql context implicts" should "work" in {      
        val testSqlctx = sqlctx
        import sqlctx.implicits._

        val workingDf = Seq(ID(1)).toDS.toDF
    }
}

为什么我不能在测试的顶层导入隐含的任何想法class?

beforeAll 运行s 在任何测试之前,但在 class 的构造函数之前没有 运行。第一个片段中的操作顺序是:

  1. 构造函数被调用,执行val testSqlctx = sqlctximport sqlctx.implicits._

  2. beforeAll 已调用

  3. 测试运行

第二个片段的操作顺序:

  1. beforeAll 已调用

  2. 测试运行,执行val testSqlctx = sqlctximport sqlctx.implicits._

假设你给你的 SparkContext 一个默认值 (null) 并在 beforeAll 中初始化它,第一个操作顺序将尝试使用 sqlctx 当它仍然是null,从而导致空指针异常。