web-dev-qa-db-fra.com

Existe-t-il un moyen simple dans xunit.net de comparer deux collections sans tenir compte de la commande des articles?

Dans l'un de mes tests, je veux m'assurer qu'une collection contient certains éléments. Par conséquent, je souhaite comparer cette collection avec les éléments d’une collection attendue et non en ce qui concerne l’ordre des éléments . Actuellement, mon code de test ressemble à ceci:

[Fact]
public void SomeTest()
{
    // Do something in Arrange and Act phase to obtain a collection
    List<int> actual = ...

    // Now the important stuff in the Assert phase
    var expected = new List<int> { 42, 87, 30 };
    Assert.Equal(expected.Count, actual.Count);
    foreach (var item in actual)
        Assert.True(expected.Contains(item));
}

Existe-t-il un moyen plus simple de réaliser cela dans xunit.net? Je ne peux pas utiliser Assert.Equal car cette méthode vérifie si l'ordre des éléments est le même dans les deux collections. J'ai jeté un oeil à Assert.Collection mais cela ne supprime pas l'instruction Assert.Equal(expected.Count, actual.Count) dans le code ci-dessus.

Merci pour vos réponses à l'avance.

15
feO2x

Brad Wilson de xunit.net m'a dit dans cette Problème Github qu'il fallait utiliser l'opérateur OrderBy de LINQ et ensuite Assert.Equal pour vérifier que deux collections contiennent des éléments égaux sans égard à leur ordre. Bien sûr, vous auriez besoin d'une propriété sur la classe d'élément correspondante que vous pouvez utiliser pour commander en premier lieu (ce que je n'avais pas vraiment dans mon cas).

Personnellement, j'ai résolu ce problème en utilisant FluentAssertions , une bibliothèque fournissant de nombreuses méthodes d'assertion pouvant être appliquées dans un style fluide. Bien sûr, il existe également de nombreuses méthodes que vous pouvez utiliser pour valider des collections .

Dans le contexte de ma question, j'utiliserais quelque chose comme le code suivant:

[Fact]
public void Foo()
{
    var first = new[] { 1, 2, 3 };
    var second = new[] { 3, 2, 1 };

    first.Should().BeEquivalentTo(second);
}

Ce test réussit car l'appel BeEquivalentTo ignore l'ordre des éléments.

Shouldly est également une bonne alternative si vous ne voulez pas utiliser FluentAssertions.

21
feO2x

Pas une Xunit, mais une réponse Linq:

bool areSame = !expected.Except(actual).Any() && expected.Count == actual.Count;

Donc dans XUnit:

Assert.True(!expected.Except(actual).Any() && expected.Count == actual.Count));

Comme @ robi-y a dit, dans Microsoft.VisualStudio.QualityTools.UnitTestFramework il y a CollectionAssert.AreEquivalent

11
rducom

Peut-être un autre moyen est:

Assert.True(expected.SequenceEqual(actual));

Cela vérifie aussi la commande. C'est ce qui se passe en interne:

using (IEnumerator<TSource> e1 = first.GetEnumerator())
using (IEnumerator<TSource> e2 = second.GetEnumerator())
{
    while (e1.MoveNext())
    {
        if (!(e2.MoveNext() && comparer.Equals(e1.Current, e2.Current))) return false;
    }
    if (e2.MoveNext()) return false;
}
return true;

Donc, si vous ne vous souciez pas de l'ordre, il suffit de commander les deux listes avant:

Assert.True(expected.OrderBy(i => i).SequenceEqual(actual.OrderBy(i => i)));
6
rducom

Vous pouvez utiliser CollectionAssert.AreEquivalent à partir de Microsoft

CollectionAssert.AreEquivalent(expected, actual);
1
mantale