gpt4 book ai didi

java - 在 JUnit 测试中检查深度相等性

转载 作者:搜寻专家 更新时间:2023-10-30 19:46:39 25 4
gpt4 key购买 nike

我正在为克隆、序列化和/或写入 XML 文件的对象编写单元测试。在这三种情况下,我都想验证生成的对象是否与原始对象“相同”。我在我的方法中经历了几次迭代,发现了所有这些方法的错误,想知道其他人做了什么。

我的第一个想法是在所有类中手动实现 equals 方法,并使用 assertEquals。在决定覆盖 equals 以对可变对象执行深度比较是一件坏事之后,我放弃了这种方法,因为您几乎总是希望集合对它们包含的可变对象使用引用相等性[1]。

然后我想我可以将方法重命名为 contentEquals 或其他名称。然而,经过更多思考,我意识到这不会帮助我找到我正在寻找的那种回归。如果程序员添加了一个新的(可变的)字段,却忘记将它添加到克隆方法中,那么他可能也会忘记将它添加到 contentEquals 方法中,而我正在编写的所有这些回归测试都将毫无值(value)。

然后我编写了一个漂亮的 assertContentEquals 函数,它使用反射来检查对象的所有(非 transient )成员的值,必要时递归检查。这避免了上述手动比较方法的问题,因为它假定默认情况下必须保留所有字段并且程序员必须显式声明要跳过的字段。但是,在某些合法情况下,克隆后字段确实不应该相同 [2]。我在 toassertContentEquals 中放入了一个额外的参数,它列出了要忽略的字段,但是由于这个列表是在单元测试中声明的,所以在递归检查的情况下它会变得非常丑陋。

所以我现在考虑重新在每个被测试的类中包含一个 contentEquals 方法,但这次使用类似于上述 assertContentsEquals 的辅助函数来实现。这样,当递归操作时,豁免将在每个单独的类中定义。

有什么意见吗?您过去是如何处理这个问题的?

编辑阐述我的想法:

[1]我从这个 article 得到了不重写可变类上的 equals 的理由.一旦将可变对象粘贴到 Set/Map 中,如果字段发生变化,则其哈希值将发生变化,但其存储桶不会发生变化,从而破坏事物。因此,选项是不覆盖可变对象上的 equals/getHash,或者有一个策略,即一旦将可变对象放入集合中就永远不更改它。

我没有提到我正在现有代码库上实现这些回归测试。在这种情况下,改变 equals 的定义,然后必须找到它可以改变软件行为的所有实例的想法让我感到害怕。我觉得我很容易破坏而不是修复。

[2]我们代码库中的一个示例是图形结构,其中每个节点都需要一个唯一标识符,以便在最终写入 XML 时用于链接节点 XML。当我们克隆这些对象时,我们希望标识符不同,但其他一切保持不变。在反复思考之后,似乎“这个对象是否已经在这个集合中”和“这些对象定义相同”的问题在这种情况下使用了根本不同的平等概念。第一个是询问身份,如果进行深入比较,我希望包括 ID,而第二个是询问相似性,我不希望包括 ID。这让我更加反对实现 equals 方法。

你们同意这个决定,还是认为实现平等是更好的方式?

最佳答案

我会采用反射方法并使用 RetentionPolicy.RUNTIME 定义自定义注释,以允许测试类的实现者标记克隆后预计会更改的字段。然后您可以使用反射检查注释并跳过标记的字段。

通过这种方式,您可以保持测试代码的通用性和简单性,并可以方便地直接在代码中标记异常,而不会影响需要测试的代码的设计或运行时行为。

注释可能如下所示:

import java.lang.annotation.*;

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD})
public @interface ChangesOnClone
{
}

这是在要测试的代码中如何使用它:

class ABC
{
private String name;

@ChangesOnClone
private Cache cache;
}

最后是测试代码的相关部分:

for ( Field field : fields )
{
if( field.getAnnotation( ChangesOnClone.class ) )
continue;
// else test it
}

关于java - 在 JUnit 测试中检查深度相等性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6065471/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com