MSTest: CollectionAssert.AreEquivalent a échoué. La collection attendue contient 1 occurrence(s) de

Question :

est-ce que quelqu'un peut me dire pourquoi le test de mon unité échoue avec ce message d'erreur?

CollectionAssert.AreEquivalent a échoué. La collection attendue contient 1 occurrence(s) de . Réel la collection contient 0 occurrence(s).

Objectif :

j'aimerais vérifier si deux listes sont identiques. Ils sont identiques si les deux contiennent les mêmes éléments avec les mêmes valeurs de propriété. L'ordre n'est pas pertinent.

exemple de Code :

c'est le code qui produit l'erreur. list1 et list2 sont identiques, c'est-à-dire qu'ils se copient l'un l'autre.

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

j'ai aussi essayé cette ligne ( source )

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

et cette ligne ( source )

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

P. S.

questions connexes sur le débordement de la cheminée:

j'ai vu ces deux questions, mais les réponses n'ont pas aidé.

20
demandé sur Community 2011-03-04 17:23:35

4 réponses

Vous avez absolument raison. À moins que vous ne fournissiez quelque chose comme un IEqualityComparer<MyPerson> ou implémenter MyPerson.Equals() , les deux objets MyPerson seront comparés avec object.Equals , tout comme n'importe quel autre objet. Puisque les objets sont différents, l'Assertion échoue.

22
répondu neontapir 2011-03-04 18:05:43

il fonctionne si j'ajoute un IEqualityComparer<T> comme décrit sur MSDN et si j'utilise Enumerable.SequenceEqual . Notez cependant que l'ordre des éléments est maintenant pertinent.

dans l'essai unitaire

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

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;
    }
}
20
répondu Lernkurve 2018-04-26 19:42:14

j'ai eu cette même erreur quand j'ai testé une collection persistened by nHibernate. J'ai été capable d'obtenir ceci pour travailler en dépassant les deux égaux et GetHashCode méthodes. Si je n'ai pas outrepassé les deux, j'ai quand même eu la même erreur que vous avez mentionnée:

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

j'avais l'objet suivant:

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

que j'ai testé en utilisant le suivant:

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

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

    tx.Commit();
}

j'utilise nHibernate qui encourage primordial de ces méthodes, de toute façon. Le seul inconvénient que je peux voir est que ma méthode égale est basée sur la clé d'affaires de l'objet et donc teste l'égalité en utilisant la clé d'affaires et pas d'autres domaines. Vous pouvez outrepasser des égaux comme vous voulez mais méfiez-vous de la pollution d'égalité mentionnée dans ce post:

CollectionAssert.AreEquivalent défaut... Je ne comprends pas pourquoi

3
répondu Joe B. 2017-05-23 12:24:24

j'ai écrit ceci pour tester des collections où l'ordre n'est pas important:

    public static bool AreCollectionsEquivalent<T>(ICollection<T> collectionA, ICollection<T> collectionB, IEqualityComparer<T> comparer)
    {
        if (collectionA.Count != collectionB.Count)
            return false;

        foreach (var a in collectionA)
        {
            if (!collectionB.Any(b => comparer.Equals(a, b)))
                return false;
        }

        return true;
    }

pas aussi élégant qu'utiliser SequenceEquals , mais ça marche.

bien sûr pour l'utiliser vous faites simplement:

Assert.IsTrue(AreCollectionsEquivalent<MyType>(collectionA, collectionB, comparer));

0
répondu Shaamaan 2012-10-08 07:47:29