Есть ли простой способ войти? xunit.net сравнить две коллекции без учета заказа предметов?

в одном из моих тестов, я хочу убедиться, что сборник имеет определенные элементы. Поэтому я хочу сравнить эту коллекцию с элементами ожидаемой коллекции не относительно порядка пунктов. В настоящее время, мой тестовый код выглядит так:

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

есть ли более простой способ достичь этого в xunit.net? Я не могу использовать Assert.Equal поскольку этот метод проверяет, является ли порядок элементов одинаковым в обеих коллекциях. Я взглянул на Assert.Collection но это не удаляет Assert.Equal(expected.Count, actual.Count) оператор в коде выше.

Спасибо за ваши ответы заранее.

4 ответов


Брэд Уилсон из xunit.net сказал мне в этом Выпуск Github что нужно использовать LINQ это OrderBy оператора, а потом Assert.Equal чтобы убедиться, что две коллекции содержат равные элементы без учета их порядка. Конечно, у вас должно быть свойство в соответствующем классе элементов, которое вы можете использовать для заказа в первую очередь (чего у меня на самом деле не было в моем случае).

лично я решил эту проблему с помощью FluentAssertions, a библиотека, которая предоставляет множество методов утверждения, которые могут быть применены в беглом стиле. Конечно,есть также много методов, которые можно использовать для проверки коллекции.

в контексте моего вопроса я бы использовал что-то вроде следующего кода:

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

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

этот тест проходит, потому что BeEquivalentTo вызов игнорирует порядок элементов.

Shouldly также является хорошей альтернативой, если вы не хотите идти с FluentAssertions.


не Xunit, а ответ Linq:

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

Так в XUnit:

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

как сказал @robi-y, в Microsoft.VisualStudio.QualityTools.UnitTestFramework здесь CollectionAssert.AreEquivalent


может быть, другой способ:

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

Это тоже проверяет порядок. Вот что происходит внутри :

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;

Так что если вы не заботитесь о порядке, просто заказать оба списка до

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

можно использовать CollectionAssert.AreEquivalent С Microsoft

CollectionAssert.AreEquivalent(expected, actual);