It appears that CollectionAssert
cannot be used with generics. This is super frustrating; the code I want to test does use generics. What am I to do? Write boilerplate to convert between the two? Manually check collection equivalence?
This fails:
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));
Compiler errors:
Error 1:
'System.Collections.Generic.IEnumerator>' does not contain a definition for 'ToList' and no extension method 'ToList' accepting a first argument of type 'System.Collections.Generic.IEnumerator>' could be found
Error 2
'System.Collections.Generic.IEnumerator>' does not contain a definition for 'ToList' and no extension method 'ToList' accepting a first argument of type 'System.Collections.Generic.IEnumerator>' could be found
Error 3
'System.Collections.Generic.IEnumerator>' does not contain a definition for 'SequenceEquals' and no extension method 'SequenceEquals' accepting a first argument of type 'System.Collections.Generic.IEnumerator>' could be found
What am I doing wrong? Am I not using extensions correctly?
Update: Ok, this looks a bit better, but still doesn't work:
IEnumerable<IDictionary<string, string>> expected = // ...
IEnumerable<IDictionary<string, string>> actual = // ...
CollectionAssert.AreEquivalent(expected.ToList(), actual.ToList()); // fails
CollectionAssert.IsSubsetOf(expected.ToList(), actual.ToList()); // fails
I don't want to be comparing lists; I only care about set membership equality. The order of the members is unimportant. How can I get around this?
You can use CollectionAssert
with generic collections. The trick is to understand that the CollectionAssert
methods operate on ICollection
, and although few generic collection interfaces implement ICollection
, List<T>
does.
Thus, you can get around this limitation by using the ToList
extension method:
IEnumerable<Foo> expected = //...
IEnumerable<Foo> actual = //...
CollectionAssert.AreEqual(expected.ToList(), actual.ToList());
That said, I still consider CollectionAssert
broken in a lot of other ways, so I tend to use Assert.IsTrue(bool)
with the LINQ extension methods, like this:
Assert.IsTrue(expected.SequenceEqual(actual));
FWIW, I'm currently using these extension methods to perform other comparisons:
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;
}
}
If you are working with Sets, then use this Idiom
HashSet<string> set1 = new HashSet<string>(){"A","B"};
HashSet<string> set2 = new HashSet<string>(){"B","A"};
Assert.IsTrue(set1.SetEquals(set2));
You could easily write your own generic version, then move it to a base or utility class that's used in all of your tests. Base it on the LINQ operators like All and Any.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With