Чтобы прокрутить этот вопрос...

Как этот тест не проходит?

[TestMethod]
public void DummyTest() {
    var expected = new List<List<string>>() {
        new List<string>(){ "123456", "25.6", "15", "a" },
        new List<string>(){ "123457", "3107450.82", "1", "bcdef" },
        new List<string>(){ "123458", "0.01", "900000", "-fgehk" }
    };

    var actual = new List<List<string>>() {
        new List<string>(){ "123456", "25.6", "15", "a" },
        new List<string>(){ "123457", "3107450.82", "1", "bcdef" },
        new List<string>(){ "123458", "0.01", "900000", "-fgehk" }
    };

    CollectionAssert.AreEqual(expected, actual);
}

Кстати, Assert.IsTrue(expected.SequenceEqual(actual)); тоже терпит неудачу.

Есть ли лучший способ проверить коллекции коллекций?

Использование .NET 4.6.1.

2
Aaron Thomas 23 Мар 2017 в 22:11

2 ответа

Лучший ответ

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

Средство сравнения равенства по умолчанию для List<string> будет сравнивать ссылки двух объектов, а не сравнивать базовые значения двух списков, потому что List не меняет это поведение по умолчанию с object ,

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

6
Servy 23 Мар 2017 в 19:32

Одним из способов реализации этого является использование следующего кода:

public static bool AreEqual<T>(IList<T> list1, IList<T> list2)
{
    if (list1?.Count != list2?.Count)
        return false;

    // order does not matter. Remove OrderBy, if it matters
    // return list1.OrderBy(_ => _).SequenceEqual(list2.OrderBy(_ => _));
    return list1.SequenceEqual(list2);
}

public static bool AreEqualListOfLists<T>(IList<List<T>> lists1, IList<List<T>> lists2)
{
    return lists1.All(innerList1 => lists2.Any(innerList2 => AreEqual(innerList1, innerList2)));
}

static void Main(string[] args)
{
    var expected = new List<List<string>>
    {
        new List<string> {"123456", "25.6", "15", "b"},
        new List<string> {"123457", "3107450.82", "1", "bcdef"},
        new List<string> {"123458", "0.01", "900000", "-fgehk"}
    };

    var actual = new List<List<string>>
    {
        new List<string> {"123456", "25.6", "15", "b"},
        new List<string> {"123457", "3107450.82", "1", "bcdef"},
        new List<string> {"123458", "0.01", "900000", "-fgehk"}
    };

    var areEqual = AreEqualListOfLists(expected, actual);
}

Это немного длиннее, чем решение SelectMany, но оно обеспечивает большую гибкость (например, если порядок не имеет значения на более глубоком уровне, его можно легко отрегулировать или предоставить значимое сообщение об ошибке при разнице).

0
Alexei 23 Мар 2017 в 19:25