Search code examples
c#unit-testingienumerable

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 non-generic 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?


Solution

  • 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...