Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/305.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何编写单元测试以确保类定义未被修改?_Java_Junit - Fatal编程技术网

Java 如何编写单元测试以确保类定义未被修改?

Java 如何编写单元测试以确保类定义未被修改?,java,junit,Java,Junit,我们有一个使用java序列化的类。这个类应该很少修改。我想写一个单元测试来执行这个规则。当这个字段被修改时,它意味着大量的更改,版本会碰撞到依赖但独立的应用程序,这些应用程序使用这个对象的java序列化调用我们的应用程序 一个想法是只使用自动生成的serialVersionUID。这样做的问题是,它可以根据JVM的更改进行修改(这很烦人) 关于如何处理这个问题还有其他想法吗 谢天谢地,这门课很平淡。或者,换句话说,类没有复杂的子类。它只是一个简单java对象(如字符串、整数和数组)的集合。最简单

我们有一个使用java序列化的类。这个类应该很少修改。我想写一个单元测试来执行这个规则。当这个字段被修改时,它意味着大量的更改,版本会碰撞到依赖但独立的应用程序,这些应用程序使用这个对象的java序列化调用我们的应用程序

一个想法是只使用自动生成的serialVersionUID。这样做的问题是,它可以根据JVM的更改进行修改(这很烦人)

关于如何处理这个问题还有其他想法吗


谢天谢地,这门课很平淡。或者,换句话说,类没有复杂的子类。它只是一个简单java对象(如字符串、整数和数组)的集合。

最简单的选择是使用反射API获取类接口、非静态和非瞬态字段、构造函数和方法的列表,并断言它们没有改变

当然,这意味着您必须对受此序列化影响的每个类执行此操作(例如,如果您的根类具有其他对象的集合)

作为参考,SVUID算法可在以下目录中找到:

serialVersionUID
是使用数据流的签名计算的 反映类定义的字节。国家科学院 使用标准与技术(NIST)安全哈希算法(SHA-1) 计算流的签名。前两个32位 数量用于形成64位哈希。A.
java.lang.DataOutputStream
用于将基本数据类型转换为 字节序列。输入到流的值由 类的Java虚拟机(VM)规范。这个 流中项目的顺序如下所示:

  • 使用UTF编码写入的类名
  • 类修饰符写为32位整数
  • 每个接口的名称,按使用UTF编码写入的名称排序
  • 对于按字段名称排序的类的每个字段(除了
    私有静态
    私有瞬态
    字段):
  • UTF编码中字段的名称
  • 字段的修饰符写为32位整数
  • UTF编码中字段的描述符
  • 如果存在类初始值设定项,请写出以下内容:
  • UTF编码中方法的名称,
  • 方法的修饰符,
    java.lang.reflect.modifier.STATIC
    ,写为32位整数
  • UTF编码中方法的描述符,
    ()V
  • 对于按方法名称和签名排序的每个非私有构造函数:
  • UTF编码中方法的名称,
  • 方法的修饰符写为32位整数
  • UTF编码中方法的描述符
  • 对于按方法名称和签名排序的每个非私有方法:
  • UTF编码中方法的名称
  • 方法的修饰符写为32位整数
  • UTF编码中方法的描述符
  • SHA-1算法在由
    DataOutputStream
    生成的字节流上执行,并生成五个32位值
    SHA[0..4]
  • 哈希值由SHA-1消息摘要的第一个和第二个32位值组合而成。如果消息的结果是 摘要,五个32位字
    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);