【问题标题】:ClassCastException when running Spark test运行 Spark 测试时出现 ClassCastException
【发布时间】:2017-12-23 14:21:17
【问题描述】:

我已将 mockito(使用 Guice)添加到我们的测试环境中,如下所示:

class SparkModuleWithMocks extends AbstractModule with JsonFormats {
override def configure(): Unit = {
  //bind(classOf[TrafficFilterRules]).toInstance(trafficFilterRulesMock)
  bind(classOf[TrafficFilterRules]).toProvider(new Provider[TrafficFilterRules]{
    override def get(): TrafficFilterRules = {
      val trafficFilterRulesMock: TrafficFilterRules = mock[TrafficFilterRules](withSettings().serializable())
      val stream = getClass.getResourceAsStream("/trafficFilterRules.json")
      val lines = scala.io.Source.fromInputStream( stream ).getLines.mkString
      val array = parse(lines).extract[List[FilterRules]].toArray
      when(trafficFilterRulesMock.trafficFilterRulesTable).thenReturn(array)
      trafficFilterRulesMock
    }
  })
  bind(classOf[SiteTable]).toProvider(new Provider[SiteTable]{
    override def get(): SiteTable = {
      val siteTableMock: SiteTable = mock[SiteTable](withSettings().serializable())
      val stream = getClass.getResourceAsStream("/siteDomains.json")
      val lines = scala.io.Source.fromInputStream( stream ).getLines.mkString
      val array = parse(lines).extract[List[SiteDomain]].toArray
      when(siteTableMock.siteDomains).thenReturn(array)
      siteTableMock
    }
  })
  bind(classOf[SparkSession]).toProvider(classOf[SparkSessionProvider])
}
}

val injectorWithMocks: Injector = Guice.createInjector(new SparkModuleWithMocks)

SparkSessionProvider 是我们自己的类,它为 guice 覆盖 get() 并构建 sparkSession。 使用 injectorWithMocks,我注入 sparkSession 和我们测试的服务,如下所示:

val sparkSession = injector.instance[SparkSession]
val clickoutService = injectorWithMocks.instance[ClickoutEnrichmentService]

当我从 Intellij 运行测试时,一切正常,但是当我从 sbt 命令行运行它时,例如:

 sbt "testOnly *ClickoutEnrichmentServiceTest"

我收到以下错误:

org.apache.spark.SparkException: Job aborted due to stage failure: 
Task 0 in stage 49.0 failed 1 times, most recent failure: Lost task 0.0 in 
stage 49.0 (TID 68, localhost, executor driver): java.lang.ClassCastException: 
cannot assign instance of scala.collection.immutable.List$SerializationProxy 
to field org.apache.spark.rdd.RDD.org$apache$spark$rdd$RDD$$dependencies_ of 
type scala.collection.Seq in instance of org.apache.spark.rdd.MapPartitionsRDD

我已经阅读了几张关于这个问题的票,但它们都与运行 spark 集群有关,而不是本地或测试模式。

谁能解释一下这个错误的原因是什么?解决这个问题的好方向是什么?

谢谢 尼尔

【问题讨论】:

    标签: scala apache-spark intellij-idea sbt mockito


    【解决方案1】:

    我也遇到过这个。我最终从@K.Chen 找到了这个问题Mockito's mock throw ClassNotFoundException in Spark application

    他为他的问题提供了一个解决方案,即使用 mock[SiteTable](withSettings().serializable(SerializableMode.ACROSS_CLASSLOADERS)) 而不是在您的代码中。即传递额外的参数SerializableMode.ACROSS_CLASSLOADERS

    不幸的是,正如他的问题所指出的那样,他不确定为什么这可以解决问题。

    在 Mockito 2.13.1 的 SerializableMode 的源代码中,我们发现以下注释: /** * Useful if the mock is deserialized in a different classloader / vm. */ @Incubating ACROSS_CLASSLOADERS source

    也许executors和master中的类加载器不一样?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-05-07
      • 2012-05-02
      • 2017-03-26
      相关资源
      最近更新 更多