MSTest:CollectionAssert.AreEquivalent失败.预期的集合包含1次出现

Ler*_*rve 22 .net c# unit-testing mstest

问题:

任何人都可以告诉我为什么我的单元测试失败了这个错误消息?

CollectionAssert.AreEquivalent失败.预期的集合包含1次出现.实际集合包含0次出现.

目标:

我想检查两个列表是否相同.如果它们包含具有相同属性值的相同元素,则它们是相同的.订单无关紧要.

代码示例:

这是产生错误的代码.list1并且list2是相同的,即彼此的复制粘贴.

[TestMethod]
public void TestListOfT()
{
    var list1 = new List<MyPerson>()
    {
        new MyPerson()
        {
            Name = "A",
            Age = 20
        },
        new MyPerson()
        {
            Name = "B",
            Age = 30
        }
    };
    var list2 = new List<MyPerson>()
    {
        new MyPerson()
        {
            Name = "A",
            Age = 20
        },
        new MyPerson()
        {
            Name = "B",
            Age = 30
        }
    };

    CollectionAssert.AreEquivalent(list1.ToList(), list2.ToList());
}

public class MyPerson
{
    public string Name { get; set; }
    public int Age { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

我也试过这一行(来源)

CollectionAssert.AreEquivalent(list1.ToList(), list2.ToList());
Run Code Online (Sandbox Code Playgroud)

这条线(来源)

CollectionAssert.AreEquivalent(list1.ToArray(), list2.ToArray());
Run Code Online (Sandbox Code Playgroud)

PS

相关Stack Overflow问题:

我已经看到了这两个问题,但答案没有帮助.

neo*_*pir 22

你是绝对正确的.除非你提供像IEqualityComparer<MyPerson>或者类似的东西,否则将比较MyPerson.Equals()两个MyPerson对象object.Equals,就像任何其他对象一样.由于对象不同,Assert将失败.

  • 感谢您的回答!我会将你的答案标记为已接受的答案,因为它解释了"为什么".我将链接到我的答案,以显示[如何"](http://stackoverflow.com/questions/5194966/mstest-collectionassert-areequivalent-failed-the-expected-collection-contains-1/5196791#5196791 ). (2认同)
  • 我从@Lernkurve的答案开始,并且效果很好。之后,我尝试将Equals和GetHashCode方法移至MyPerson类,使其也实现IEqualityComparer &lt;MyPerson&gt;。我希望Assert.IsTrue(list1.SequenceEqual(list2)); 现在将在MyPerson上使用IEqualityComparer实现,但不会。我得到“ Assert.IsTrue失败”。因此,您的建议“ ...或实现MyPerson.Equals()”似乎不起作用。我不懂为什么。 (2认同)

Ler*_*rve 21

如果我IEqualityComparer<T>按照MSDN上的描述添加一个并且我使用它,它是有效的Enumerable.SequenceEqual.但请注意,现在元素的顺序是相关的.

在单元测试中

//CollectionAssert.AreEquivalent(list1, list2); // Does not work
Assert.IsTrue(list1.SequenceEqual(list2, new MyPersonEqualityComparer())); // Works
Run Code Online (Sandbox Code Playgroud)

的IEqualityComparer

public class MyPersonEqualityComparer : IEqualityComparer<MyPerson>
{
    public bool Equals(MyPerson x, MyPerson y)
    {
        if (object.ReferenceEquals(x, y)) return true;

        if (object.ReferenceEquals(x, null) || object.ReferenceEquals(y, null)) return false;

        return x.Name == y.Name && x.Age == y.Age;
    }

    public int GetHashCode(MyPerson obj)
    {
        if (object.ReferenceEquals(obj, null)) return 0;

        int hashCodeName = obj.Name == null ? 0 : obj.Name.GetHashCode();
        int hasCodeAge = obj.Age.GetHashCode();

        return hashCodeName ^ hasCodeAge;
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 为什么CollectionAssert.AreEquivalent失败?如果我想使用AreEquivalent因为订单不重要怎么办? (5认同)

小智 5

在测试 nHibernate 持久化的集合时,我遇到了同样的错误。我能够通过覆盖Equals 和 GetHashCode方法来实现这一点。如果我没有覆盖两者,我仍然会遇到您提到的相同错误:

CollectionAssert.AreEquivalent failed. The expected collection contains 1 occurrence(s) of . 
The actual collection contains 0 occurrence(s).
Run Code Online (Sandbox Code Playgroud)

我有以下对象:

public class EVProjectLedger
{
    public virtual long Id { get; protected set; }
    public virtual string ProjId { get; set; }
    public virtual string Ledger { get; set; }
    public virtual AccountRule AccountRule { get; set; }
    public virtual int AccountLength { get; set; }
    public virtual string AccountSubstrMethod { get; set; }

    private Iesi.Collections.Generic.ISet<Contract> myContracts = new HashedSet<Contract>();

    public virtual Iesi.Collections.Generic.ISet<Contract> Contracts
    {
        get { return myContracts; }
        set { myContracts = value; }
    }

    public override bool Equals(object obj)
    {
        EVProjectLedger evProjectLedger = (EVProjectLedger)obj;
        return ProjId == evProjectLedger.ProjId && Ledger == evProjectLedger.Ledger;
    }
    public override int GetHashCode()
    {
        return new { ProjId, Ledger }.GetHashCode();
    }
}
Run Code Online (Sandbox Code Playgroud)

我使用以下方法进行了测试:

using (ITransaction tx = session.BeginTransaction())
{
    var evProject = session.Get<EVProject>("C0G");

    CollectionAssert.AreEquivalent(TestData._evProjectLedgers.ToList(), evProject.EVProjectLedgers.ToList());

    tx.Commit();
}
Run Code Online (Sandbox Code Playgroud)

我正在使用 nHibernate,它鼓励无论如何覆盖这些方法。我可以看到的一个缺点是我的 Equals 方法基于对象的业务键,因此使用业务键而不是其他字段来测试相等性。您可以随心所欲地覆盖 Equals,但要注意本文中提到的平等污染:

CollectionAssert.AreEquivalent 失败......不知道为什么