Search code examples
c#unit-testingarchitecturecode-coveragedotcover

How to test or exclude private unreachable code from code coverage


I have a bunch of assemblies with near 100% test coverage but I often run into a situation like in the example below. I cannot test the default switch case, which is there to guard against future bugs where I add more items to the enum but forget to update the switch statement to support new items.

I would like to be able to either find a pattern where I can eliminate that "untestable" code, test it or mark that line of code (but not the entire method) to be excluded by the coverage analysis.

It may sound silly but I do not want to assume the default case will never happen, and I do not want to bundle the default case with one that already exist. I want the exception to be thrown when I create such bugs. Which will happen sooner or later.

I use DotCover to calculate coverage at the moment.

Note: This is just example code but I think it illustrates a fairly common pattern.

public class Tester
{
    private enum StuffToDo
    {
        Swim = 0, 
        Bike,
        Run
    }

    public void DoSomeRandomStuff()
    {
        var random = new Random();
        DoStuff((StuffToDo)random.Next(3));
    }

    private void DoStuff(StuffToDo stuff)
    {
        switch (stuff)
        {
            case StuffToDo.Swim:
                break;
            case StuffToDo.Bike:
                break;
            case StuffToDo.Run:
                break;
            default:
                // How do I test or exclude this line from coverage?
                throw new ArgumentOutOfRangeException("stuff");
        }
    }
}

Solution

  • Private methods are always candidates to be extracted into its own classes. Especially, if they hold complex logic, like yours do. I suggest you make a StuffDoer class with the DoStuff() as a public method and inject it into your Tester class. Then you have:

    • A DoStuff() method, reachable by tests
    • A DoSomeRandomStuff() method that can be tested with a mock instead of relying on the outcome of DoStuff(), thus making it a true unit test.
    • NO SRP-violation.
    • All in all, nice, crisp and SOLID code.