如何模拟 sqlContext.read.parquet()?

How to mock sqlContext.read.parquet()?

class Test{
override def execute(sqlContext: SQLContext) {
  val df: DataFrame = sqlContext.read.parquet(path)
}

如何模拟 sqlContext.read.parquet?调用时需要从 json 和 return 中读取虚拟数据帧

class XTest extends FunSuite with MockitoSugar {

test("Test") {

val sparkSession = SparkSession
  .builder()
  .master("local[*]")
  .appName("View_Persistence_Spark_Job")
  .getOrCreate()
sparkSession.sparkContext.setLogLevel("ERROR")

val test = new Test()
val df_from_json = sparkSession.read.option("multiline", "true").json("src/test/resources/test.json")
    val mockContext = mock[SQLContext]
        when(mockContext.read.parquet("src/test/resources/test.json")).thenReturn(df_from_json)
    test.execute(sparkSession.sqlContext)

有 2 个问题需要从您的示例中理解。

首先,使用模拟时不能连接调用。正在尝试:

when(mockContext.read.parquet("src/test/resources/test.json"))

总是会失败,因为结果mockContext没有实现读取的方法,所以会导致空引用异常。为了解决这个问题,我们需要添加另一个模拟,这将是 mockContext.read 的结果。所以这部分将是:

val mockContext = mock[SQLContext]
val dataFrameReader = mock[DataFrameReader]

when(mockContext.read).thenReturn(dataFrameReader)
when(dataFrameReader.parquet("src/test/resources/test.json")).thenReturn(df_from_json)

第二件事,为了让 test 使用那个模拟,你需要把它传递给他,而不是 sparkSession.sqlContext,这不是模拟,因此你不能覆盖它的行为.

总而言之,一个完整的测试将是:

test("Test") {

  val sparkSession = SparkSession
    .builder()
    .master("local[*]")
    .appName("View_Persistence_Spark_Job")
    .getOrCreate()
  sparkSession.sparkContext.setLogLevel("ERROR")

  val test = new Test()
  val df_from_json: sql.DataFrame = sparkSession.read.option("multiline", "true").json("src/test/resources/test.json")
  val mockContext = mock[SQLContext]
  val dataFrameReader = mock[DataFrameReader]

  when(mockContext.read).thenReturn(dataFrameReader)
  when(dataFrameReader.parquet("src/test/resources/test.json")).thenReturn(df_from_json)
  test.execute(mockContext)
}