Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C#: How do you test the IEnumerable.GetEnumerator() method?

Let's say I for example have this class that generates Fibonacci numbers:

public class FibonacciSequence : IEnumerable<ulong>
{
    public IEnumerator<ulong> GetEnumerator()
    {
        var a = 0UL;
        var b = 1UL;
        var c = a + b;
        while (true)
        {
            yield return c;
            c = a + b;
            a = b;
            b = c;
        }
    }
    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }
}

I can then write a test that makes sure that the n first numbers in the sequence are correct.

    [Test]
    public void GetEnumerator_FirstFifteenNumbers_AreCorrect()
    {
        var sequence = new FibonacciSequence().Take(15).ToArray();
        CollectionAssert.AreEqual(sequence, new[] {1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610});
    }

When I check for coverage however, I will see that the IEnumerable.GetEnumerator() method is untested, and my coverage will be lower than it really needs to be. Fair enough. But how should I test that method?

How do you usually deal with this?

like image 484
Svish Avatar asked Oct 02 '09 14:10

Svish


2 Answers

EDIT: Updated based on what Marc said.

Well you could get the coverage up by doing:

// Helper extension method
public static IEnumerable AsWeakEnumerable(this IEnumerable source)
{
    foreach (object o in source)
    {
        yield return o;
    }
}

...

[Test]
public void GetEnumerator_FirstFifteenNumbers_AreCorrect()
{
    IEnumerable weak = new FibonacciSequence().AsWeakEnumerable();
    var sequence = weak.Cast<int>().Take(15).ToArray();
    CollectionAssert.AreEqual(sequence, 
        new[] {1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610});
}

Note that weak is declared to be the nongeneric IEnumerable type... which means you need to call Cast on it to cast each returned object to int.

I'm not sure I'd bother though...

like image 71
Jon Skeet Avatar answered Oct 10 '22 08:10

Jon Skeet


You would have to use use IEnumerable (non-generic); I posted a reply using Cast<T>, but that will still cheat (it checked for the desired type as a special case) - you might need something like:

public static int CountUntyped(this IEnumerable source) {
    int count = 0;
    foreach(object obj in source) { count++; }
    return count;
}

IEnumerable<T> source = ...
Assert.AreEqual(typed.Count(), source.CountUntyped());
like image 37
Marc Gravell Avatar answered Oct 10 '22 09:10

Marc Gravell