如何在单元测试中测试两个对象是否相等?

How to test equality of two objects in unit tests?

我有一个项目,在该项目中我接收作为 DTO 的对象并将它们转换为视图模型。为了进行这种转换,我决定制作自定义转换器,它会进行一些计算,以便将 DTO 属性转换为视图模型。在所有这些准备就绪并且转换正常后,我想向转换添加一些单元测试以使其更稳定(我知道这不符合 TDD,但这是我设法做到的)。

当我想要测试来验证两个视图模型是否相等时,问题就来了

Assert.AreEqual(expected, actual);

因为视图模型的 none 定义了 Equals 方法,它们永远不会相等作为参考。我考虑并发现了一些比较这些对象的方法:

  1. 定义Equals方法。但我不知道定义它是否是一个好习惯,仅用于测试目的。而且如果我定义的话,也会推荐GetHashCode方法也定义,所以我感觉这个方案不是最好的

  2. 我想到的另一种可能性是在测试项目中实现IEqualityComparer<T>,将比较逻辑与主转换项目隔离,甚至将其提取到第三个项目中,因此转换如果有必要,模块可以在将来使用它。这个实现看起来不错,但我不知道是否值得再添加一个有很多类的项目,也应该测试一下。

  3. 我在 Stack Overflow question 上找到的第三种方法看起来很有趣,它是序列化两个对象并比较字符串。问题是我不知道这是不是编程的好习惯

以下哪一种是比较对象的最佳方式?我是否遗漏了一些可能更有效的方法?

注意:View-Models是复杂的对象,我不能改变转换为其他技术的方式。

我非常喜欢 Fluent Assertions 的 ShouldBeEquivalentTo 方法。

actual.ShouldBeEquivalentTo(expected);

默认情况下,这个 "just works",假设您传入的两个对象在结构上是等效的,但您可以提供额外的参数来自定义您希望它进行比较的方式。例如,如果你只想检查对象的几部分是否等价,你可以说:

actual.ShouldBeEquivalentTo(new {
    expected.Name,
    expected.Description,
    expected.Code
}, options =>
    options.ExcludingMissingMembers);

您的第二种方法比其他两种方法要好得多,因为它将特定于测试的代码与单元测试放在一起,还因为它允许您更改对两个视图模型相等的含义的定义。

不过,将相等比较器移动到一个单独的项目中几乎不值得:如果您打算共享相等比较逻辑,那么您不妨将它放入您的对象中。另一方面,如果它仅设计用于测试,那么您应该将它与测试放在一起(即使用您的方法 #1)。

基于序列化的方法太脆弱了,因为它依赖于一个不相关的特性(即序列化)来测试你实际测试的特性(即转换)。