加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

scala – 为什么方法参数会导致Mockito出现NotSerializableExcep

发布时间:2020-12-16 09:56:52 所属栏目:安全 来源:网络整理
导读:我有一些使用spark运行的 Scala代码,但我简化了它们: // Not Serializableclass Configobject FileReader extends FileReaderclass FileReader extends Serializable { def read(config: Config): String = config.getClass.toString}object Task extends T
我有一些使用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)
  }
}

不是Config不可序列化.

我想为它们编写一些测试,并且Task的实例需要是Serializable,因为它可以被序列化并发送给spark worker.

我使用此函数来检查对象是否可以序列化:

def checkSerializable(obj: AnyRef,name: String) = {
  println("### checking " + name + ": " + obj.getClass)
  new ObjectOutputStream(new ByteArrayOutputStream()).writeObject(obj)
  println(name + " ok")
}

首先让我们检查是否可以序列化正常的Task实例:

val task = new Task(new FileReader)
checkSerializable(task,"no-mockito")

输出:

### checking no-mockito: class Task
no-mockito ok

似乎没问题.

但我想用Mockito模拟FileReader,所以我的代码将是:

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")

它报告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)

这很奇怪,因为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")

它仍然失败,另一个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)

在使用Mockito时,不确定为什么配置实例会包含在任务中?以及如何避免它?

演示项目:https://github.com/freewind/mockito-serialization-issue,你可以克隆它并运行demo / MockitoDemo.scala

更新:

另一个值得注意的事情是:如果我删除这一行

fileReader.read(config)

来自Task,这意味着任务将是:

class Task(fileReader: FileReader) extends Serializable {
  def execute(config: Config): Unit = {
    // removed this line: fileReader.read(config)
  }
}

不再抛出NotSerializableException(我没有更改测试代码)

解决方法

您可能需要使FileReader模拟序列化也尝试:

val fileReader = Mockito.mock(classOf[FileReader],Mockito.withSettings().serializable())

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读