单元测试具有许多私有方法的复杂类

时间:2010-04-29 15:33:21

标签: unit-testing testing dependency-injection mocking separation-of-concerns

我有一个带有一个公共方法的类和许多私有方法,这些方法根据传递给public方法的参数运行,所以我的代码看起来像:

public class SomeComplexClass
{
    IRepository _repository;

    public SomeComplexClass()
       this(new Repository())
    {
    }

    public SomeComplexClass(IRepository repository)
    {
        _repository = repository;
    }


    public List<int> SomeComplexCalcualation(int option)
    {
        var list = new List<int>();

        if (option == 1)
            list = CalculateOptionOne();
        else if (option == 2)
            list = CalculateOptionTwo();
        else if (option == 3)
            list = CalculateOptionThree();
        else if (option == 4)
            list = CalculateOptionFour();
        else if (option == 5)
            list = CalculateOptionFive();

        return list;
    }

    private List<int> CalculateOptionOne()
    {
        // Some calculation
    }

    private List<int> CalculateOptionTwo()
    {
        // Some calculation
    }

    private List<int> CalculateOptionThree()
    {
        // Some calculation
    }

    private List<int> CalculateOptionFour()
    {
        // Some calculation
    }

    private List<int> CalculateOptionFive()
    {
        // Some calculation
    }
}

我想过几种方法来测试这个类,但是所有这些方法看起来都过于复杂,或者比我想要的更多地暴露方法。到目前为止的选项是:

  • 将所有私有方法设置为内部并使用[assembly:InternalsVisibleTo()]

  • 将所有私有方法分离到一个单独的类中并创建一个接口。

  • 将所有方法设为虚拟,并在我的测试中创建一个继承自此类的新类并覆盖方法。

是否还有其他测试上述课程的选项会比我列出的更好?

如果您选择我列出的其中一个,您能解释一下原因吗?

由于

5 个答案:

答案 0 :(得分:7)

您无需更改界面即可测试这些方法。只需彻底测试公共接口,确保测试所有私有方法:

 void Test1() 
 {
      new SomeComplexClass(foo).SomeComplexCalcualation(1);
 } 

 void Test2() 
 {
      new SomeComplexClass(foo).SomeComplexCalcualation(2);
 } 

依旧......

您可以使用覆盖工具(例如,NCover for .NET)来确保您要测试的所有代码都已经过测试。

答案 1 :(得分:3)

原始类调度工作的OptionCalculators如何?每个只有一个方法,CalculateOption,当然它是公开的,因此很容易测试。

答案 2 :(得分:0)

您应该只需要测试类/接口的公共方法。

您只需要确保您有足够的单元测试用例来彻底测试这些公共方法的所有不同行为(这将适当地超越私有方法)。

答案 3 :(得分:0)

如果这些计算中的每一个都很复杂,那么每个计算真的是一个单一的方法吗?如果这些计算共享代码,或者每个应该是多个方法,那么它就是您提到的接口/策略方法的一个参数,因此您可以测试每个步骤。

另一件需要考虑的事情:彻底运用一种公共方法就是测试两件事  a)ComputeOptionN代码正在运行,AND  b)选项检查工作正常。

如果你实际上是在传递int,但不理想,这不是问题,特别是如果比较可能变得更复杂,或者它可能会改变。

答案 4 :(得分:0)

@Carl是对的。这只不过是利用战略模式。将所有calculator存储在一个数组中,将数组注入SomeComplexClass。这样您就可以自己和calculator对每个SomeComplexClass进行单元测试。现在你可以这样做:

public List<int> SomeComplexCalcualation(int option)
{
     return calculator.find(option);
}

非常容易模仿calculator