我在十多年前的代码中有以下逻辑,我必须编写单元测试。它是一个具体的类,以下逻辑在于ctor。是否有一种很好的方法可以为这样的遗留代码编写单元测试/模拟。我正在使用MSTest / RhinoMocks框架和VS 2010 IDE与.Net framework 4.0
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
}
}
}
答案 0 :(得分:6)
单元测试遗留代码很棘手。通常,您必须首先重构才能编写单元测试。您最好的选择是非常小的重构步骤,逐步提高可测试性,同时让测试阶段处于“工作”状态。我建议:
1.)引入“感知”变量,允许您在关键位置(即DB调用之前和之后)验证被测试类的内部状态。这将允许您编写测试来验证类的当前行为(基于公共感知变量),而不必非常重构。根据这些测试验证类的行为并开始重构。感知变量是临时的,一旦完成重构就应该删除。他们只能在同一时间编写测试,因此您可以安全地进行重构。
2.)逐个替换对具体类的引用,以接口通过构造函数传递的接口。对于单例,你有两个选项,一个是让Singleton返回一个特殊的单元测试实例 - 这需要修改Singleton实现,但是要保持你的测试类不变。您可以执行此操作,直到您可以重构使用接口依赖项来替换Singleton。
另外,我建议选择Working Effectively with Legacy Code的副本,详细描述这一步骤重构,特别是依赖于依赖性的技术。
答案 1 :(得分:1)
除了BrokenGlass所说的,您可能还需要考虑编写一些集成测试,以确保整个过程正常运行。例如,如果您的应用程序更新了数据库中的某些行,请编写与测试数据库相对的可重复测试,以便您可以在重构并将整个内容分解为松散耦合的可测试块时继续确保正确的功能。
没有什么比重构一个类,为它编写一堆测试,然后意识到你的重构破坏了应用程序中的其他东西更糟糕的事情。