Подтвердить что ты не робот

Использование CollectionAssert с дженериками?

Похоже, что CollectionAssert нельзя использовать с дженериками. Это супер разочаровывает; код, который я хочу проверить, использует дженерики. Что мне делать? Напишите шаблон для преобразования между ними? Вручную проверить эквивалентность коллекции?

Это не удается:

ICollection<IDictionary<string, string>> expected = // ...

IEnumerable<IDictionary<string, string>> actual = // ...

// error 1 and 2 here
CollectionAssert.AreEqual(expected.GetEnumerator().ToList(), actual.ToList());

// error 3 here
Assert.IsTrue(expected.GetEnumerator().SequenceEquals(actual));

Ошибки компилятора:

Ошибка 1:

'System.Collections.Generic.IEnumerator > ' не содержит определения для "ToList" и не используется метод расширения "ToList", принимающий первый аргумент типа "System.Collections.Generic.IEnumerator > ", который можно найти

Ошибка 2

'System.Collections.Generic.IEnumerator > ' не содержит определения для "ToList" и не используется метод расширения "ToList", принимающий первый аргумент типа "System.Collections.Generic.IEnumerator > ", который можно найти

Ошибка 3

'System.Collections.Generic.IEnumerator > ' не содержит определения для 'SequenceEquals' и не может быть найден метод расширения 'SequenceEquals', принимающий первый аргумент типа 'System.Collections.Generic.IEnumerator > '

Что я делаю неправильно? Я не правильно использую расширения?

Обновление: Хорошо, это выглядит немного лучше, но все равно не работает:

IEnumerable<IDictionary<string, string>> expected = // ...

IEnumerable<IDictionary<string, string>> actual = // ...

CollectionAssert.AreEquivalent(expected.ToList(), actual.ToList()); // fails
CollectionAssert.IsSubsetOf(expected.ToList(), actual.ToList()); // fails

Я не хочу сравнивать списки; Я только забочусь о равенстве членства. Порядок членов неважен. Как я могу обойти это?

4b9b3361

Ответ 1

Вы можете использовать CollectionAssert с общими коллекциями. Хитрость заключается в том, чтобы понять, что методы CollectionAssert работают на ICollection, и хотя некоторые общие интерфейсы коллекции реализуют ICollection, List<T> делает.

Таким образом, вы можете обойти это ограничение, используя метод расширения ToList:

IEnumerable<Foo> expected = //...
IEnumerable<Foo> actual = //...
CollectionAssert.AreEqual(expected.ToList(), actual.ToList());

Тем не менее, я все еще считаю, что CollectionAssert разбит многими другими способами, поэтому я предпочитаю использовать Assert.IsTrue с помощью методов расширения LINQ, например:

Assert.IsTrue(expected.SequenceEquals(actual));

FWIW, я в настоящее время использую эти методы расширения для выполнения других сравнений:

public static class EnumerableExtension
{
    public static bool IsEquivalentTo(this IEnumerable first, IEnumerable second)
    {
        var secondList = second.Cast<object>().ToList();
        foreach (var item in first)
        {
            var index = secondList.FindIndex(item.Equals);
            if (index < 0)
            {
                return false;
            }
            secondList.RemoveAt(index);
        }
        return secondList.Count == 0;
    }

    public static bool IsSubsetOf(this IEnumerable first, IEnumerable second)
    {
        var secondList = second.Cast<object>().ToList();
        foreach (var item in first)
        {
            var index = secondList.FindIndex(item.Equals);
            if (index < 0)
            {
                return false;
            }
            secondList.RemoveAt(index);
        }
        return true;
    }
}

Ответ 2

Если вы работаете с наборами, используйте этот Idiom

HashSet<string> set1  = new HashSet<string>(){"A","B"};
HashSet<string> set2  = new HashSet<string>(){"B","A"};

Assert.IsTrue(set1.SetEquals(set2));

Ответ 3

Вы можете легко написать свою собственную общую версию, а затем перенести ее на базовый или служебный класс, который использовался во всех ваших тестах. Настройте его на операторы LINQ, такие как "Все" и "Любой".