【问题标题】:ASP.Net XUnit check if list of objects cointains a specific objectASP.Net XUnit 检查对象列表是否包含特定对象
【发布时间】:2020-05-29 12:26:50
【问题描述】:

我正在尝试将单元测试添加到我的项目中。其中一些测试正在检查对象列表是否不包含对象。为了检查列表是否包含我尝试过的对象Assert.Contains(MyList, ExpectedObject),但它仍然给出一个错误,指出列表不包含该对象。即使在调试测试时,我也可以看到该对象已正确添加到列表中。

Assert.DoesNotContain(MyList, ExpectedObject) 也是如此。当我从列表中删除一个项目并执行此检查时,它确实说它不在列表中。但是当我不再删除该项目时,它仍然说它不再在列表中。即使它仍在列表中。

当我尝试使用测试列表时:List<string>。并执行添加和删除项目的相同操作,然后检查这些项目是否在列表中。它确实有效。 也许Assert.Contains 不适用于对象列表。但是编译器没有给出任何错误。而且我还检查了ExpectedObject 是否与列表中的对象类型相同。

是否有另一种检查对象是否在列表中的方法。 任何帮助表示赞赏。

【问题讨论】:

    标签: c# asp.net-mvc list unit-testing


    【解决方案1】:

    在您的测试中,ExpectedObject 是列表中的实际对象还是具有相同值的对象?在 C# 中,具有相同属性值的两个对象实际上并不相等。我怀疑这就是你的测试失败的原因。具有相同值的两个字符串被认为是相等的,因为字符串对象实现了 Equals 方法(和some more),就像@dorukerenaktas 指出的那样。

    有多种方法可以解决这个问题。最简单的方法是检查具有预期属性值的对象是否在集合中。

    Assert.Contains 的重载允许您指定谓词,例如:

    Assert.Contains(MyList, item => item.Id == expectedId)
    

    另一个选择是覆盖对象上的Equals 方法,就像@dorukerenaktas 解释的那样,但我只建议如果它真的对你的类有意义。我绝对不会这样做只是为了让你可以在测试中使用它。

    【讨论】:

    • 是的,我正在比较具有相同值的不同对象。您提供的示例有效。非常感谢!
    【解决方案2】:

    通常在 Java 和 C# 中,对象列表的 contains 方法的实现通过 equals 方法比较它们。如果默认情况下未为对象指定 equals 方法,它将查找对象的唯一 ID 或内存地址,这意味着即使有 2 个具有所有相同字段的对象也可以不同。因为他们分别创建并分配了不同的内存地址。如果要比较对象,请覆盖 equals 方法。这将允许 contains 方法使用您的自定义比较方法来比较对象。

    示例:

    假设您有一个 Person 对象,其中包含 id、name、mail 等字段。如果您希望对象在其 id 相同的情况下相等,则可以使用:

    // They are same person if their id is same
    public override bool Equals(Object obj)
       {
          Person personObj = obj as Person;
          if (personObj == null)
             return false;
          else
             return idNumber.Equals(personObj.idNumber);
       }
    

    【讨论】:

    • 但我无法覆盖 Equals 方法,因为我已经在使用它了。
    • 覆盖后可以继续使用。但它的行为会因实现而异。
    • 真的没有其他方法可以用 XUnit 检查对象是否在列表中吗?
    • 您可以遍历列表并检查每个元素是否相等。如果它们都不相等Assert.Fail(reason); 如果您想要“包含”行为。如果您想在循环后检测“不包含”是否有任何一项等于Assert.Fail(reason);
    【解决方案3】:

    我之前也遇到过类似的问题,我使用 fluentAssertions 来解决它。

    因此,例如,如果您有一个名为 myList 的对象列表,则此片段应该可以解决问题。

    myList.Should().Contain(expectedItem);
    

    这里有更多关于收藏的信息:https://fluentassertions.com/collections/

    另一个选项是遍历列表并检查是否有任何对象等于您的对象。执行此操作时,如果您使用 ShouldBeEquivalentTo() 方法,则无需检查每个属性的相等性。如果您的对象很大或嵌套,这将非常有用,因为此方法会递归检查每个属性。

    actual.Should().BeEquivalentTo(expected);
    

    这里有更多信息:https://fluentassertions.com/objectgraphs/

    我喜欢使用 fluentAssetions,因为它使我的测试和断言更具可读性,并且在确实发生错误或断言失败时提供非常清晰的消息,因此您可以更快地发现问题。

    【讨论】:

      猜你喜欢
      • 2019-07-04
      • 2021-09-18
      • 2022-11-09
      • 2017-08-10
      • 2015-03-15
      • 2012-10-17
      • 2012-05-24
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多