gpt4 book ai didi

java - 通过 Spark 反/序列化时,使用 void 方法的模拟会导致 'local class name incompatible with stream class name "void"'

转载 作者:行者123 更新时间:2023-11-30 01:49:26 24 4
gpt4 key购买 nike

当尝试使用 Spark 为应用程序创建测试时,我遇到以下错误:

java.io.InvalidClassException: java.lang.Void; local class name incompatible with stream class name "void"
at java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:620)
at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1843)
at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1713)
at java.io.ObjectInputStream.readClass(ObjectInputStream.java:1678)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1518)
at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:2245)
at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:2169)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2027)

只有当我模拟一些具有 void 方法的类时,才会发生这种情况,这些方法将在测试单元运行期间的某个时刻被调用。

例如我的代码是:

public class MyTest {

private MyClass uut;

private Writer writer;

@Captor
private ArgumentCaptor<Dataset<Row>> rowCaptor;

@Before
public void setUp() {
initMocks(this);

writer = mock(Writer.class);
uut = new MyClass(writer);
}

@Test
public void testSomething() {
// given

// when
uut.process();

// then
verify(writer, times(2)).write(rowCaptor.capture());
List<Dataset<Row>> result = rowCaptor.getAllValues();
// ...
}
}

最佳答案

问题似乎出在 Mockito 序列化其内部代理类的方式上。如果您在 Spark 中运行的任务/作业实际上被序列化和反序列化,那么只会产生负面影响。

org.apache.spark.scheduler.ShuffleMapTask#runTask任务被反序列化。 Spark 此时基本上所做的是:

new JavaDeserializationStream(new ByteBufferInputStream(ByteBuffer.wrap(this.taskBinary.value())), ClassLoader.getSystemClassLoader()).objIn.readObject()

它会产生与

完全相同的错误消息
new ObjectInputStream(new ByteArrayInputStream(this.taskBinary.value())).readObject()

哪个可以工作并正确解析对象。

特别是 Java/Spark 的期望 void 之间似乎不匹配。要序列化的方法与 Mockito 实际执行的操作:"java.lang.Void"/"Void""void" .

幸运的是,Mockito 允许您指定它序列化模拟的方式:

MockSettings mockSettings = Mockito.withSettings().serializable(SerializableMode.ACROSS_CLASSLOADERS);
writer = mock(Writer.class, mockSettings);

进行此更改后,测试应该可以工作。

<小时/>

请注意verify例如,如果模拟被序列化、发送到某个地方、反序列化然后再次使用,调用就很棘手/将无法按预期工作。模拟上的调用对原始 writer 不可见.

关于java - 通过 Spark 反/序列化时,使用 void 方法的模拟会导致 'local class name incompatible with stream class name "void"',我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56579623/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com