Java 如何编写单元测试以确保类定义未被修改?
我们有一个使用java序列化的类。这个类应该很少修改。我想写一个单元测试来执行这个规则。当这个字段被修改时,它意味着大量的更改,版本会碰撞到依赖但独立的应用程序,这些应用程序使用这个对象的java序列化调用我们的应用程序 一个想法是只使用自动生成的serialVersionUID。这样做的问题是,它可以根据JVM的更改进行修改(这很烦人) 关于如何处理这个问题还有其他想法吗Java 如何编写单元测试以确保类定义未被修改?,java,junit,Java,Junit,我们有一个使用java序列化的类。这个类应该很少修改。我想写一个单元测试来执行这个规则。当这个字段被修改时,它意味着大量的更改,版本会碰撞到依赖但独立的应用程序,这些应用程序使用这个对象的java序列化调用我们的应用程序 一个想法是只使用自动生成的serialVersionUID。这样做的问题是,它可以根据JVM的更改进行修改(这很烦人) 关于如何处理这个问题还有其他想法吗 谢天谢地,这门课很平淡。或者,换句话说,类没有复杂的子类。它只是一个简单java对象(如字符串、整数和数组)的集合。最简单
谢天谢地,这门课很平淡。或者,换句话说,类没有复杂的子类。它只是一个简单java对象(如字符串、整数和数组)的集合。最简单的选择是使用反射API获取类接口、非静态和非瞬态字段、构造函数和方法的列表,并断言它们没有改变 当然,这意味着您必须对受此序列化影响的每个类执行此操作(例如,如果您的根类具有其他对象的集合) 作为参考,SVUID算法可在以下目录中找到:
serialVersionUID
是使用数据流的签名计算的
反映类定义的字节。国家科学院
使用标准与技术(NIST)安全哈希算法(SHA-1)
计算流的签名。前两个32位
数量用于形成64位哈希。A.
java.lang.DataOutputStream
用于将基本数据类型转换为
字节序列。输入到流的值由
类的Java虚拟机(VM)规范。这个
流中项目的顺序如下所示:
私有静态
和私有瞬态
字段):
java.lang.reflect.modifier.STATIC
,写为32位整数()V
DataOutputStream
生成的字节流上执行,并生成五个32位值SHA[0..4]
H0 H1 H2 H3 H4
,位于五个字的数组中
int
名为sha的值,哈希值的计算如下:
long散列=((sha[0]>>24)和0xFF)
|(sha[0]>>>16)&0xFF)>>8)&0xFF)>>0)&0xFF)>>24)&0xFF)>>16)&0xFF)>>8)&0xFF)>>0)&0xFF)这也是我能想到的最好答案。我放弃了这个想法,转而使用措辞强硬的评论。在课堂上。希望他们不会被忽视。不管怎样,谢谢你的帮助。我认为这将是最好的方法,它只是比我愿意花更多的精力来解决这个问题。我添加了使用ASM框架为现有类计算serialVersionUID值的示例。
SerialVersionUIDAdder svuidv = new SerialVersionUIDAdder(Opcodes.ASM5, null) {
public FieldVisitor visitField(int access, String name, String desc, String signature, Object value) {
if ("serialVersionUID".equals(name)) {
return null;
}
return super.visitField(access, name, desc, signature, value);
}
protected void addSVUID(long svuid) {
if(svuid!=expectedsvid) {
throw new AssertionError("Serialization issue!");
}
}
};
InputStream is = AA.class.getResourceAsStream("/" + AA.class.getName().replace('.', '/') + ".class");
ClassReader cr = new ClassReader(is);
cr.accept(svuidv, ClassReader.SKIP_CODE);