Java 无法在单元测试方法之前和之后启动/停止spark in

Java 无法在单元测试方法之前和之后启动/停止spark in,java,unit-testing,apache-spark,junit,Java,Unit Testing,Apache Spark,Junit,我正在为spark应用程序编写单元测试,但遇到了一个问题。理想情况下,我希望有一个Before和After方法,在这里我启动和停止spark(而不是在单元测试方法本身中这样做) 下面的实现工作正常,我能够在测试开始时声明SparkConf和JavaSparkContext,然后在测试结束时执行sc.close() @Test public void testMethod(){ SparkConf conf = new SparkConf().setMaster("loca

我正在为spark应用程序编写单元测试,但遇到了一个问题。理想情况下,我希望有一个
Before
After
方法,在这里我启动和停止spark(而不是在单元测试方法本身中这样做)

下面的实现工作正常,我能够在测试开始时声明
SparkConf
JavaSparkContext
,然后在测试结束时执行
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()
}
但是我想设置它,这样开始和停止都有自己的方法

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

@After
public void close(){
    sc.close();
}
你知道为什么后者不起作用吗?我将遇到一个异常,即某些对象不可序列化

  • 首先,
    sc
    应该是一个类字段,而不是
    init()
    方法的局部变量
  • 其次,在课前使用
    @BeforeClass
    和课后使用
    @AfterClass
    不是更好吗?Spark start相当长(web ui、集群等每次都会启动),如果完全隔离不是问题,那么
    @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)
    }
    }
    
    public类SomeSparkTest实现可序列化{
    私有静态瞬态JavaSparkContext jsc;
    @课前
    公共静态void init(){
    SparkConf conf=new SparkConf().setMaster(“本地”).setAppName(“testGeoHashAggregation”);
    jsc=新的JavaSparkContext(conf);
    }
    @下课
    公共静态无效关闭(){
    jsc.close();
    }
    @试验
    公共空间应该发生一些事情(){
    //给定
    //RDD的制备
    JavaRDD=jsc.textFile(…)
    //什么时候
    //行动
    长计数=rdd.count()
    //然后
    //验证输出;来自断言的资产,不需要
    资产(计数)。isEqualTo(5)
    }
    }
    
    您已经从Spark存储库获得了一些测试套件


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

    第二个代码看起来很奇怪-我想
    JavaSparkContext
    不仅在
    init()
    中,而且在类中。如果序列化的问题在于某个对象,只需
    实现可序列化的接口即可。如果您对
    JavaSparkContext
    的序列化有问题,请将transient添加到此字段。类似于->
    公共类YourClass{private transient JavaSparkContext sc;…这里的所有代码都是以前的…之后的
    谢谢,我把JavaSparkContext作为一个类字段,但不确定为什么我把它作为init的一个局部变量写进去。总之,将其设置为transient解决了我的问题。我没有考虑在
    之前的
    之前的
    nks寻求帮助!@rvisio好的,所以只需将Serializable添加到测试类中,并将JavaSparkContext标记为transient。应该可以工作:)