如何从代码覆盖中测试或排除私有无法访问的代码

Jak*_*lås 20 c# architecture unit-testing code-coverage dotcover

我有一堆接近100%测试覆盖率的程序集,但我经常遇到如下例所示的情况.我无法测试默认的开关案例,这是为了防范未来的错误,我在枚举中添加了更多的项目,但忘记更新switch语句以支持新项目.

我希望能够找到一种模式,我可以消除"不可测试的"代码,测试它或标记要覆盖分析排除的代码行(但不是整个方法).

这可能听起来很愚蠢,但我不想假设默认情况永远不会发生,我不想将默认情况与已经存在的情况捆绑在一起.我希望在创建此类错误时抛出异常.迟早会发生这种情况.

我目前使用DotCover来计算覆盖率.

注意:只是示例代码,但我认为它说明了一种相当常见的模式.

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");
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Mor*_*ten 9

私有方法总是被提取到自己的类中的候选者.特别是,如果他们持有复杂的逻辑,就像你的那样.我建议你StuffDoerDoStuff()一个公共方法创建一个类,然后将它注入你的Tester类.然后你有:

  • 一种DoStuff()可通过测试获得的方法
  • DoSomeRandomStuff()可与模拟的而不是依靠的结果进行测试方法DoStuff(),从而使之成为真正的单元测试.
  • 没有SRP违规.
  • 总而言之,漂亮,清晰和SOLID代码.

  • 同意,这是我通常做的(有或没有注射).但是,根据枚举的来源(例如在原型定义中共享),可能会有很多像这样的小方法.有时,通过创建那些额外的方法和类("Doers"),代码将变得更加复杂和难以维护. (2认同)
  • @JakobMöllås:根据我的经验,所有这些小方法都会弄乱一个包含大量代码的类,这些代码是测试无法实现的.通过仔细命名,命名空间层次结构和文件夹结构,我更喜欢尊重SRP的小类,并且很容易测试.恕我直言,适当的单元测试是迄今为止可维护代码的最大贡献者. (2认同)
  • +1我真的同意这一点.在实际方面,在处理遗留代码库时很难匆匆忙忙.我的答案中的内容通常是快速能够测试遗留代码的中间步骤. (2认同)