【问题标题】:Unable to start/stop spark in Before and After methods in Unit Test无法在单元测试的之前和之后方法中启动/停止火花
【发布时间】:2016-10-06 04:43:32
【问题描述】:

我正在为我的 spark 应用程序编写单元测试,但遇到了问题。理想情况下,我想要一个BeforeAfter 方法来启动和停止spark(而不是在单元测试方法本身中进行)。

以下实现有效,我可以在测试开始时声明SparkConfJavaSparkContext,然后在最后执行sc.close()

@Test
public void testMethod(){
            SparkConf conf = new SparkConf().setMaster("local").setAppName("testGeoHashAggregation");
            JavaSparkContext sc = new JavaSparkContext(conf);

            // yadda yadda yadda   
            //tests here

            sc.close()
}

但我想设置一下,让 start 和 stop 有自己的方法

@Before
public void init(){
        SparkConf conf = new SparkConf().setMaster("local").setAppName("testGeoHashAggregation");
        JavaSparkContext sc = new JavaSparkContext(conf);
}

@After
public void close(){
    sc.close();
}

任何想法为什么后者不起作用?我会遇到一些对象不可序列化的异常。

【问题讨论】:

  • 第二个代码看起来很奇怪——我想JavaSparkContext 不仅在init() 中,而且在课堂上。如果序列化问题出在某个对象上 - 只是implement Serializable 接口。如果您对JavaSparkContext 的序列化有问题,请将瞬态添加到此字段。类似 -> public class YourClass { private transient JavaSparkContext sc; .... all code here with Before ... After

标签: java unit-testing apache-spark junit


【解决方案1】:
  1. 首先sc应该是一个类字段,而不是init ()方法的局部变量
  2. 其次,使用@BeforeClass@AfterClass不是更好吗? spark启动时间比较长(web ui、cluster等每次都在启动),如果完全隔离没问题,那么@BeforeClass会更好。然而,这只是一个建议,而不是您问题的解决方案。

因此,代码将如下所示:

public class SomeSparkTest implements Serializable {

private static transient JavaSparkContext jsc;

@BeforeClass 
public static void init () {
    SparkConf conf = new SparkConf().setMaster("local").setAppName("testGeoHashAggregation");
    jsc = new JavaSparkContext(conf);
}

@AfterClass
public static void close(){
    jsc.close();
}

@Test 
public void shouldSomethingHappend () {
    // given 
    // preparation of RDDs
    JavaRDD<String> rdd = jsc.textFile(...)

    // when
    // actions
    long count = rdd.count()

    // then
    // verify output; assertThat is from FestAssertions, not necessary
    assertThat(count).isEqualTo(5)
}
}

Here 你已经从 Spark 存储库中获得了一些测试套件

说明:您在测试中使用的任何 lambda 或内部类都引用了外部类,在这种情况下它是测试类。 Spark 总是序列化 lambdas/内部类,即使在本地集群模式下也是如此。如果你的测试类是不可序列化的或者如果它有任何不可序列化的字段,那么就会出现这样的错误

【讨论】:

  • 谢谢,我有 JavaSparkContext 作为类字段,但不知道为什么我把它写成 init 的局部变量。无论如何,将其设置为瞬态解决了我的问题。我没有考虑过BeforeClassBefore。会调查的,谢谢你的帮助!
  • @rvisio 好的,所以只需将 Serializable 添加到您的测试类并将 JavaSparkContext 标记为瞬态。应该工作:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-01-05
  • 1970-01-01
  • 2011-03-02
相关资源
最近更新 更多