I would like to know if any of the classes in the .net framework that implement IEnumerable doesn't implement the ICollection interface.
I'm asking it because I can't get 100% code coverage in the following extension method that I wrote:
public static int GetSafeCount<T>(this IEnumerable<T> nullableCollaction)
{
if (nullableCollaction == null)
{
return 0;
}
var collection = nullableCollaction as ICollection<T>;
if (collection != null)
{
return collection.Count;
}
return nullableCollaction.Count();
}
The last line is not covered in any of my tests and I can't find the correct class to instantiate in order to cover it.
my test code is:
[Test]
public void GetSafeCount_NullObject_Return0()
{
IEnumerable<string> enumerable=null;
Assert.AreEqual(0, enumerable.GetSafeCount());
}
[Test]
public void GetSafeCount_NonICollectionObject_ReturnCount()
{
IEnumerable<string> enumerable = new string[]{};
Assert.AreEqual(0, enumerable.GetSafeCount());
}
Just use any LINQ operation, e.g. Where
:
[Test]
public void GetSafeCount_NonICollectionObject_ReturnCount()
{
IEnumerable<string> enumerable = new string[0].Where(x => x.Length == 0);
Assert.AreEqual(0, enumerable.GetSafeCount());
}
However, you can simplify your implementation by just deferring to Enumerable.Count()
, which I'd expect to be optimized every way you'd like it to be:
public static int GetSafeCount<T>(this IEnumerable<T> nullableCollection)
=> nullableCollection == null ? 0 : nullableCollection.Count();
Or:
public static int GetSafeCount<T>(this IEnumerable<T> nullableCollection)
=> nullableCollection?.Count() ?? 0;
(Both assume C# 6...)
At that point, it makes sense to only have two tests: one for a null argument, one for a non-null argument.
See more on this question at Stackoverflow