我的java项目中有上千个类。其中一些实现了可序列化的接口。现在这里有一个问题。可能有人可以进入一个类,添加一个既不是 transient 也不是可序列化的新变量。代码编译得很好,但是进程在运行时会崩溃。
为了说明这一点
class Foo implements Serializable { .... // all good }
class Foo implements Serializable
{
// OOps, executorService is not serializable. It's not declared as transient either
private ExecutorService executorService = ..
}
我正在考虑写一个单元测试,它将遍历所有类并确保“真正的可序列化性”。我读过一些关于序列化特定对象的讨论。我理解这个过程,但它需要
1)创建对象。
2)序列化,然后
3)正在还原序列化。
是否有更有效和实用的方法。也许使用反射。检查所有类,如果类有可序列化的,那么所有属性都必须是可序列化的或有 transient 关键字。
有什么想法?
4条答案
按热度按时间luaexgnf1#
1)创建对象。2)序列化,然后3)反序列化。
这份清单并不完整;您还需要初始化。请考虑以下示例:
你可以对第一个进行序列化和反序列化,但是在第二个上你会得到
NotSerializableException
。更复杂的是,如果使用接口,你永远无法判断一个类是否会通过序列化,因为它是这个接口后面的class的具体对象,将被流传输:如果您可以保证所有类和类使用的类都满足以下条件:
然后测试序列化。但这确实是一个很难的条件,不是吗?否则,正确的初始化就需要手工操作了。
您可以用不同的方式使用反映:遍历要检查的
Class
对象列表,获取它们的Field[]
,并验证它们是 transient 的(Field.getModifiers()
),还是直接(Field.getType().getInterfaces()
)或间接(通过超接口或类)实现Serializable
。正如Ryan正确指出的那样,如果代码足够邪恶,这种静态序列化检查就会失败:
或者仅仅是
readObject()/writeObject()
的实现不好。要针对这类问题进行测试,您需要实际测试序列化过程,而不是它背后的代码。xv8emn3q2#
如果序列化是应用的关键部分,那么在测试中包括序列化。
编辑:
randomlyPopulateFields
的一个简单实现:z31licg03#
将您要测试的类放入
initParameters()
方法中,并将整个类作为JUnit测试运行。yrefmtwq4#
这个单元测试在
packageName
中查找Serializable
的所有后代类,并检查这些类的声明属性,看它们是否也是Serializable
的后代。库依赖关系
单元测试器