C# - 单元测试/模拟 - 旧代码

3

我需要为一个十年以上历史的代码编写单元测试,以下逻辑位于具体类的构造函数中。如何为这样的遗留代码编写单元测试/模拟测试?我使用MSTest/RhinoMocks框架和带有.Net framework 4.0的VS 2010 IDE。

public class SomeClass
    {
        /// ctor
        public SomeClass(XmlNode node)
        {
            //Step 1: Initialise some private variable based on attributes values from the node

            //Step 2: Lot of If , else -if statements ---> something like - 

            if (/*attributeValue is something*/)
            {
                // Connect to Db, fetch  some value based on the attribute value. 
                // Again the logic of connecting and fetching is in another concrete class
            }
            else if (/*attributeValue is somthing else*/)
            {
                // fetch a value by loading a config file (this loading and reading of config file 
                // is again a singleton class where config file path is hardcoded)
            }
            else
            {
                // set some private member variable 
            }
        }
    }

1
如果您无法重构以实现可测试性,您可以考虑使用像TypeMock Isolator这样的产品。不过它会花费您一定的资金... - Nathan Ratcliff
2个回答

6
单元测试遗留代码很棘手。通常情况下,您必须先进行重构才能编写单元测试。最好的方法是采用非常小的重构步骤,一步一步地提高可测试性,同时保持被测试类处于“工作”状态。我建议:
1.) 引入“感应”变量,使您能够在关键位置(即DB调用之前和之后)验证被测试类的内部状态。这将使您能够编写测试,根据公共感应变量验证类的当前行为,而无需进行大量重构。根据这些测试验证类的行为,并开始重构。感应变量是临时的,完成重构后应将其删除。它们只是为了能够在此期间编写测试,以便您可以相对安全地进行重构。
2.) 逐个将对具体类的引用替换为通过构造函数传递的接口引用。对于单例,您有两个选择,一个是让单例返回一个特殊的实例以进行单元测试-这需要修改单例实现但不更改您的被测试类。您可以这样做,直到可以重构以使用接口依赖项替换单例。
我建议您购买《遗留代码重构效能指南》,该书详细介绍了逐步重构和特别是打破依赖关系的技巧。

对于感应变量,可以使用+1。我已经通过构造函数注入日志接口实现了良好的结果,测试时可以使用简单的内存记录器进行断言。 - Darren Lewis
问题在于,如果您首先进行重构,则无法确保提供与原始代码相同的功能。在我看来,先测试再重构,尽管有时可能非常困难甚至不可能。 - Morten

1
除了BrokenGlass所说的,您可能还想考虑编写一些集成测试来确保整个过程正常工作。例如,如果您的应用程序更新数据库中的某些行,请编写可重复运行的测试,针对测试数据库进行测试,以便在重构并将整个过程分解为松散耦合的可测试块时,您可以继续确保正确的功能。
没有什么比重构一个类,为其编写一堆测试,然后意识到您的重构破坏了应用程序中的其他东西更糟糕的了。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接