簡體   English   中英

模擬 Spark DataFrameReader.option

[英]Mock Spark DataFrameReader .option

我想在我有 header 時進行參數化,然后在我從 Spark 讀取 csv 時進行分隔符。 我寫了這個:

DataFrameReader dataFrameReader = spark.read();

    dataFrameReader = "csv".equalsIgnoreCase(params.getReadFileType()) ?
                dataFrameReader
                        .option("sep",params.getDelimiter())
                        .option("header",params.isHeader())
                :dataFrameReader;

我是 Groovy 的新手,我沒有得到 dataFrameReader.option corrected mocked。

DataFrameReader dfReaderLoader = Mock(DataFrameReader)
DataFrameReader dfReaderOptionString = Mock(DataFrameReader)
DataFrameReader dfReaderOptionBoolean = Mock(DataFrameReader)

SparkSession sparkSession = Mock(SparkSession)
sparkSession.read() >> dfReaderLoader
dfReaderLoader.option(_ as String, _ as String) >> dfReaderOptionString
dfReaderOptionString.option(_ as String, _ as Boolean) >>  dfReaderOptionBoolean

它給了我一個 null 指針異常。

java.lang.NullPointerException:無法調用“org.apache.spark.sql.DataFrameReader.option(String, boolean)”因為“org.apache.spark.sql.StringReader.StringReader.StringReader”的返回值是null

如果您真的不關心構建器模式的中間調用,即返回自身的 object。 我建議使用Stub ,如果方法返回類型與其類型匹配,它將返回自身,或者您可以使用此聲明_ >> _Mocks實現相同的效果。

given:
ThingBuilder builder = Mock() {
  _ >> _
}

when:
Thing thing = builder
  .id("id-42")
  .name("spock")
  .weight(100)
  .build()

then:
1 * builder.build() >> new Thing(id: 'id-1337') // <-- only assert the last call you actually care about
thing.id == 'id-1337'

話雖如此,如果您只是刪除option的第二個參數的as String轉換,或者按照錯誤建議將其修復as Boolean ,則錯誤可能會消失 go。

我不知道你的問題是什么,但我的猜測是你創建了模擬,但不要將它們注入你的 class 被測。 如果你這樣做,你自己的版本以及 Leonard 建議的帶有默認響應的改進版本都有效:

Class 待測 + helper class:

class UnderTest {
  SparkSession spark
  Parameters params

  DataFrameReader produce() {
    DataFrameReader dataFrameReader = spark.read()

    dataFrameReader = "csv".equalsIgnoreCase(params.getReadFileType()) ?
      dataFrameReader
        .option("sep", params.getDelimiter())
        .option("header", params.isHeader())
      : dataFrameReader
  }
}
class Parameters {
  String readFileType
  String delimiter
  boolean header
}

斯波克規格:

package de.scrum_master.stackoverflow.q74923254

import org.apache.spark.sql.DataFrameReader
import org.apache.spark.sql.SparkSession
import org.spockframework.mock.MockUtil
import spock.lang.Specification

class DataFrameReaderTest extends Specification {
  def 'read #readFileType data'() {
    given:
    DataFrameReader dfReaderLoader = Mock(DataFrameReader)
    DataFrameReader dfReaderOptionString = Mock(DataFrameReader)
    DataFrameReader dfReaderOptionBoolean = Mock(DataFrameReader)

    SparkSession sparkSession = Mock(SparkSession)
    sparkSession.read() >> dfReaderLoader
    dfReaderLoader.option(_ as String, _ as String) >> dfReaderOptionString
    dfReaderOptionString.option(_ as String, _ as Boolean) >> dfReaderOptionBoolean

    def underTest = new UnderTest(spark: sparkSession, params: parameters)

    expect:
    underTest.produce().toString().contains(returnedMockName)

    where:
    readFileType | parameters                                                               | returnedMockName
    'CSV'        | new Parameters(readFileType: readFileType, delimiter: ';', header: true) | 'dfReaderOptionBoolean'
    'XLS'        | new Parameters(readFileType: readFileType)                               | 'dfReaderLoader'
  }

  def 'read #readFileType data (improved)'() {
    given:
    SparkSession sparkSession = Mock() {
      read() >> Mock(DataFrameReader) {
        _ >> _
      }
    }

    def parameters = new Parameters(readFileType: readFileType, delimiter: ';', header: true)
    def underTest = new UnderTest(spark: sparkSession, params: parameters)

    expect:
    new MockUtil().isMock(underTest.produce())

    where:
    readFileType << ['CSV', 'XLS']
  }
}

Groovy Web 控制台試試。

在您的 IDE 中,結果應該與此類似:

DataFrameReaderTest ✔
├─ read #readFileType data ✔
│  ├─ read CSV data ✔
│  └─ read XLS data ✔
└─ read #readFileType data (improved) ✔
   ├─ read CSV data (improved) ✔
   └─ read XLS data (improved) ✔

錯誤在參數中。我沒有發送定界符或 Header,所以它給出了錯誤。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM