Fre*_*ind 6 serialization scala mockito apache-spark
我有一些使用spark运行的Scala代码,但我简化了它们:
// Not Serializable
class Config
object FileReader extends FileReader
class FileReader extends Serializable {
def read(config: Config): String = config.getClass.toString
}
object Task extends Task(FileReader)
class Task(fileReader: FileReader) extends Serializable {
def execute(config: Config): Unit = {
fileReader.read(config)
}
}
Run Code Online (Sandbox Code Playgroud)
不是Config
不是Serializable
.
我想为它们编写一些测试,并且Task
需要的实例是Serializable
因为它可能被序列化并发送给spark worker.
我使用此函数来检查对象是否可以序列化:
def checkSerializable(obj: AnyRef, name: String) = {
println("### checking " + name + ": " + obj.getClass)
new ObjectOutputStream(new ByteArrayOutputStream()).writeObject(obj)
println(name + " ok")
}
Run Code Online (Sandbox Code Playgroud)
首先让我们检查是否Task
可以序列化正常实例:
val task = new Task(new FileReader)
checkSerializable(task, "no-mockito")
Run Code Online (Sandbox Code Playgroud)
输出:
### checking no-mockito: class Task
no-mockito ok
Run Code Online (Sandbox Code Playgroud)
似乎没问题.
但我想FileReader
用Mockito嘲笑,所以我的代码将是:
val fileReader = Mockito.mock(classOf[FileReader])
val config = Mockito.mock(classOf[Config])
Mockito.when(fileReader.read(config)).thenReturn("mocked")
val task = new Task(fileReader)
checkSerializable(task, "with-mockito1")
Run Code Online (Sandbox Code Playgroud)
它报告Config
不可序列化的错误:
### checking with-mockito1: class Task
java.io.NotSerializableException: Config$$EnhancerByMockitoWithCGLIB$$c7dcb0a5
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1165)
at java.io.ObjectOutputStream.writeArray(ObjectOutputStream.java:1359)
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1155)
at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1535)
at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1496)
Run Code Online (Sandbox Code Playgroud)
这很奇怪,因为config
只是一些方法参数,而不是类字段!
我修改了我的代码以使config
序列化:
val fileReader = Mockito.mock(classOf[FileReader])
val config = Mockito.mock(classOf[Config], Mockito.withSettings().serializable())
Mockito.when(fileReader.read(config)).thenReturn("mocked")
val task = new Task(fileReader)
checkSerializable(task, "with-mockito2")
Run Code Online (Sandbox Code Playgroud)
它仍然失败,另一个NotSerializableException
:
### checking with-mockito2: class Task
java.io.NotSerializableException: org.mockito.internal.creation.DelegatingMethod
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1165)
at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1535)
at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1496)
at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1413)
Run Code Online (Sandbox Code Playgroud)
不确定为什么config
在task
与Mockito合作时会包含实例?以及如何避免它?
演示项目:https://github.com/freewind/mockito-serialization-issue,你可以克隆它并运行demo/MockitoDemo.scala
更新:
另一个值得注意的事情是:如果我删除这一行
fileReader.read(config)
Run Code Online (Sandbox Code Playgroud)
来自Task
,这意味着Task
将:
class Task(fileReader: FileReader) extends Serializable {
def execute(config: Config): Unit = {
// removed this line: fileReader.read(config)
}
}
Run Code Online (Sandbox Code Playgroud)
不会NotSerializableException
再抛出(我没有更改测试代码)
您可能需要使FileReader模拟序列化也尝试:
val fileReader = Mockito.mock(classOf[FileReader], Mockito.withSettings().serializable())
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
2008 次 |
最近记录: |