C# 如何在单元测试中测试两个对象的相等性?

C# 如何在单元测试中测试两个对象的相等性?,c#,unit-testing,architecture,compare,equality,C#,Unit Testing,Architecture,Compare,Equality,我有一个项目,在这个项目中,我接收对象作为DTO,并将它们转换为视图模型。为了进行这种转换,我决定制作自定义转换器,它会进行一些计算,以便将DTOs属性转换为视图模型。在所有这些都准备好,转换工作正常之后,我想向转换中添加一些单元测试,以使其更稳定(我知道这不尊重TDD,但这是我设法做到的) 当我需要测试来验证两个视图模型的相等性时,问题就出现了 Assert.AreEqual(expected, actual); 因为没有一个视图模型定义了Equals方法,并且它们作为参考永远不会相等。我考

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

当我需要测试来验证两个视图模型的相等性时,问题就出现了

Assert.AreEqual(expected, actual);
因为没有一个视图模型定义了
Equals
方法,并且它们作为参考永远不会相等。我考虑并发现了一些方法来比较这些对象:

  • 定义
    等于
    方法。但是我不知道定义它是否是一个好的实践,只是为了测试目的。如果我定义它,建议也定义
    GetHashCode
    方法,所以我觉得这个解决方案不是最好的

  • 我认为的另一种可能性是在测试项目中实现
    IEqualityComparer
    ,将比较逻辑与主转换项目隔离,或者甚至将其提取到第三个项目中,以便转换模块将来在必要时使用它。这个实现看起来不错,但我不知道是否值得添加另一个包含许多类的项目,这些类也应该进行测试

  • 我在a上发现的第三种方法(看起来很有趣)是序列化两个对象并比较字符串。问题是,我不知道这是否是一个好的编程实践

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


    注意:视图模型是复杂的对象,我无法改变转换到其他技术的方式。

    我非常喜欢Fluent Assertions的
    应该与
    方法等效

    actual.ShouldBeEquivalentTo(expected);
    
    默认情况下,如果传入的两个对象在结构上是等效的,则此“仅起作用”,但您可以提供其他参数来自定义您希望它如何进行比较。例如,如果您只想检查几块对象的等效性,您可以说:

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

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

    但是,将相等比较程序移动到单独的项目中是不值得的:如果您想要共享相等比较逻辑,那么您最好将其放入您的对象中。另一方面,如果它只是为测试而设计的,那么您应该将它与测试放在一起(即使用您的方法#1)


    基于序列化的方法过于脆弱,因为它依赖于不相关的功能(即序列化)来测试您实际测试的功能(即转换).

    似乎您已经概述了优点和缺点-我不相信序列化,除非它们是相同的类型-有很多原因可以解释为什么具有相同属性的两个类型可以不同地序列化。@DStanley它们将始终是相同的类型,或者现在看起来是这样,虽然我正在使用
    IEqualityComparer
    中的泛型类型参数创建一个方法,该方法从
    IEqualityComparer
    接收两个对象,而不是简单的比较,来序列化它们并返回它们的字符串比较?这样是否足够稳定?@DStanley我可以看到你投票结束了这个问题,因为太宽了,但我已经阅读了帮助中心的“太宽意味着什么”,我认为这个问题不适合该部分,因为它的答案不需要在书中打洞,甚至不需要很长的答案。请考虑,许多其他编程问题可以有多个答案,这是好的,但没有一个使它们过于宽泛。非常感谢。事实上,我(和其他4个人)投票以基于意见的方式关闭了它,因为您提出的所有解决方案在技术上都是可行的,所以“最佳”通常是意见的问题。无论如何,你已经接受了一个答案,所以“没有伤害,没有犯规”。@DStanley我理解这一点,但任何其他建议都会很好,我认为保持这个问题的开放性不会有任何伤害。我仍然尊重你的决定!