问题描述
我有用于运行 Spark 作业的 Scala 代码。在运行时,主类使用反射来加载抽象类的所有实现,这些实现可以作为火花作业运行,并根据命令行参数选择正确的实现,例如spark-submit etl.jar job-name-i-want-to-run
。我正在运行 spark 3.0.1 和 Scala 2.12.10。当我尝试使用 spark-submit 运行它时,它工作得很好,但我尝试编写一个单元测试(使用 scalatest v3.2.2)并且它在 NoSuchFieldException
块上的 job.getField("MODULE$")
失败,用于子类SparkJob
在 test
文件夹内的包中声明。请注意,实现是在 object
中完成的,而不是在类中。所以我的问题是:为什么它对主文件夹中的子类有效,但对测试包中声明的子类无效(特别是仅用于测试此功能)?
import org.reflections.Reflections
object SparkJobLauncher {
def runSparkJob(args: Array[String]): Unit = {
val availableJobs = loadSparkJobs()
availableJobs(args(0)).run(args)
}
private def loadSparkJobs(): Map[String,SparkJob] = {
new Reflections("com.parent.package")
.getSubTypesOf(classOf[SparkJob])
.asScala
.map(job => {
val instance = job.getField("MODULE$").get(null).asInstanceOf[SparkJob]
(instance.name,instance)
})
.filter(_ != null)
.toMap
}
}
SparkJob 抽象类的实现如下所示:
abstract class SparkJob {
def name: String
def run(args: Array[String]): Unit
// ... other helper methods ...
}
一份工作可能是这样的:
object MyEtlJob extends SparkJob {
override def name = "my-etl"
override def run(args: Array[String]): Unit = {
// do spark stuff...
}
}
单元测试非常简单:
class SparkJobLauncherTest extends AnyFunSuite {
test("Run job") {
SparkJobLauncher.runSparkJob(Array("test"))
}
}
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)