五、 从现有代码生成测试
Visual Studio 2008支持你从现有代码自动地生成单元测试。为此,你可以右击一个类中的任何方法并且选择“Create Unit Tests…”选项。
图6—从现有代码自动生成的一个单元测试
一般说来,每一位测试驱动开发者都会不同程度地使用以前遗留(或别人提供)的现成的代码。所以,如果你需要在现有代码上添加单元测试的话,那么你可以利用这个选项来快速地创建必要的测试方法相应的基本代码部分。
【注意】关于使用这个方法添加单元测试目前尚存在一个BUG。如果你在一个ASP.NET MVC Web应用程序工程的一个类上使用这个选项,那么,你会看到将打开一个单元测试向导。但遗憾的是,这个向导生成的单元测试是执行于一个web服务器的上下文环境下。显然,这个类型的单元测试是不适合于测试驱动开发的,因为它的执行需要花费太长的时间。因此,我推荐你仅当使用类库工程时才使用本节中所描述的方法生成单元测试。
六、 测试私有方法、属性和域
当遵循良好的测试驱动开发思想进行开发时,你应当测试你的所有的代码,包括你的应用程序中定义的私有方法。那么,该如何测试你的测试工程中定义的私有方法呢?乍看起来,问题似乎是:不能从一个单元测试内部调用私有方法。
针对上面这个问题存在两种解决方案.首先,Visual Studio 2008可以生成一个类以暴露被测试类的所有私有类型的成员。在Visual Studio 2008中,你可以从代码编辑器中右击任何类,然后选择菜单选项创建私有访问器(即“Create Private Accessor”)。选择这个菜单选项将生成一个新类。借助于这个新类,它能够把所有的私有方法、属性和域暴露为公共类型的方法、属性和域.
例如,假定你想测试一个名字为Calculate的类中包含的一个名字为Subtract()的私有类型方法,那么,你可以右击这个类来生成一个访问器(Accessor),见图7。
图7—创建一个私有类型的访问器(Accessor)
在你创建该访问器后,你可以把它应用于你的单元测试代码中来测试该Subtract方法。例如,列表5中提供的单元测试将测试是否该subtract方法返回7–5的正确结果。
列表5—CalculateTest.cs(访问器)
public void SubtractTest()
{
int result = Calculate_Accessor.Subtract(7, 5);
Assert.AreEqual(result, 7 - 5);
}
注意:在列表5中,Subtract()方法在Calculate_Accessor类上而不是为Calculate类所调用.因为该Subtract()方法是私有类型的,所以你不能够在Calculate类上调用它。然而,生成的Calculate_Accessor类却恰到好处地暴露了该方法。
如果你愿意,你可以使用命令行方式生成上面这个访问器(Accessor)类。Visual Studio提供了一个现成的命令行工具,名字为Publicize.exe,能够帮助你针对一个类的private类型成员生成一个对应的公共类型的成员。
测试私有类方法的第二种方法是使用.NET反射原理。借助于反射原理,你可以绕过访问限制来调用一个类的任何类型的方法和任何类的属性。列表6提供的测试代理正是使用反射技术来调用私有的Calculate.Subtract()方法。
列表6—CalculateTest.cs(反射原理)
public void SubtractTest()
{
MethodInfo method = typeof(Calculate).GetMethod("Subtract",
BindingFlags.NonPublic | BindingFlags.Static);
int result = (int)method.Invoke(null, new object[] { 7, 5 });
Assert.AreEqual(result, 7 - 5);
}
列表6中的代码通过调用一个MethodInfo对象(用于描述Subtract方法)的Invoke()方法最终调用了私有的静态类型的Subtract()方法。(我建议你把这样的代码打包进一个工具类中以便日后把它轻松地重用于其它测试)。