.net MSTest:CollectionAssert.AreEquivalent失败,预期的集合包含1个以下项

ruoxqz4g  于 2023-11-20  发布在  .NET
关注(0)|答案(5)|浏览(102)

问题

有谁能告诉我为什么我的单元测试失败并显示此错误消息?
CollectionAssert.AreEquivalent失败。预期的集合包含出现1次的。实际的集合包含出现0次的。

目标

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

代码示例

这是产生错误的代码。list1list2是相同的,即彼此的复制粘贴。

[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; }
}

字符串
我也试过这条线(来源)

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


这条线(来源)

CollectionAssert.AreEquivalent(list1.ToArray(), list2.ToArray());


P.S.
Stack Overflow相关问题:
我看过这两个问题,但答案没有帮助。

n3schb8v

n3schb8v1#

你说的完全正确。除非你提供类似IEqualityComparer<MyPerson>的东西或实现MyPerson.Equals(),否则两个MyPerson对象将与object.Equals进行比较,就像任何其他对象一样。由于对象不同,Assert将失败。

nkoocmlb

nkoocmlb2#

如果我像MSDN上描述的那样添加一个IEqualityComparer<T>,如果我使用Enumerable.SequenceEqual,它就可以工作。

在单元测试中

//CollectionAssert.AreEquivalent(list1, list2); // Does not work
Assert.IsTrue(list1.SequenceEqual(list2, new MyPersonEqualityComparer())); // Works

字符串

IconityComparer

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;
    }
}

sshcrbum

sshcrbum3#

我在测试一个nHibernate持久化的集合时也遇到了同样的错误。我可以通过覆盖Equals和GetHashCode方法来让它工作。如果我不覆盖这两个方法,我仍然会遇到你提到的同样的错误:

CollectionAssert.AreEquivalent failed. The expected collection contains 1 occurrence(s) of . 
The actual collection contains 0 occurrence(s).

字符串
我有以下对象:

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();
    }
}


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

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

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

    tx.Commit();
}


我使用的是nHibernate,它鼓励重写这些方法。我可以看到的一个缺点是,我的Equals方法是基于对象的业务键,因此使用业务键而不是其他字段来测试相等性。你可以随心所欲地重写Equals,但要注意这篇文章中提到的相等性污染:
CollectionAssert.AreEquivalent failing... can't figure out why

mw3dktmi

mw3dktmi4#

如果你想在不编写相等比较器的情况下实现这一点,你可以使用一个单元测试库,名为FluentAssertions
https://fluentassertions.com/documentation/
它有许多内置的平等扩展功能,包括集合的功能。你可以通过Nuget安装它,它非常容易使用。
以问题中的例子为例,你最后要写的是

list1.Should().BeEquivalentTo(list2);

字符串
默认情况下,顺序在两个集合中很重要,但也可以更改。

2w3kk1z5

2w3kk1z55#

它有一个简单的答案。由于对象是不同的,不能比较,你可以简单地添加一个.ToString()

CollectionAssert.AreEquivalent(list1.ToString(), list2.ToString());

字符串

相关问题