Использование 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
Я не хочу сравнивать списки; Я только забочусь о равенстве членства. Порядок членов неважен. Как я могу обойти это?
Ответы
Ответ 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, такие как "Все" и "Любой".