Test Driven Development 的步骤是先写测试,然后写代码让测试通过,然后再重构。这些概念在.net环境中由于对软件质量要求的提高,越来越受到重视。测试公有方法是很容易的,自然而然的就有问题产生了“如何测试protected或private方法”?本文包括:
l 总结一些测试私有方法的常用做法;
l 给出一些有用的方法,即使你不知道哪种方法最优;
l 提高代码演示这些测试技术。
2. 背景
2.1. 是否应该测试私有方法?
在GOOGLE(Google search)上搜索一下就会发现无数相关讨论,更不用说实际的测试实现了。下面的表格对这些讨论做了总结,并把利弊都列出如下:
观点 |
利 |
弊 |
使用私有方法 |
|
|
测试私有方法 |
|
|
赞成和反对的人都是比较厉害的角色。我既不打算也不期望结束这些争论,我只想了解他们各自在测试中的用处。即使你不想测试私有方法:
l 但如果你知道如何测试,你的意见就更有效(而不会因为你不知道就简单的说“不测试”);
l 针对测试非公有方法可以帮助你的团队工作的更好;
l 只要可能,就值得找到一个简便的方法测试他们。
2.2. 好的标准和不准确的技术
Andrew Hunt and David Thomas 在他的书中, Pragmatic Unit Testing in C# with NUnit, 说明好的单元测试应该具有下面的特点(ATRIP):
l 自动化;
l 充分;
l 可重复;
l 独立的;
l 专业的;
针对私有/保护方法的完全测试,还有其它三项标准
l 透明:不要修改系统到测试环境(system under test),如在发布代码中封装测试代码;
l 范围:能在debug/release模式下运行;
l 简单性:使用简单,易于修改且风险小。
记住这些标准,这里有几个简单的策略:
策略 |
问题 |
不要有任何私有方法 |
|
使用#if DEBUG ... #endif 封装私有方法为公有方法,这样测试方法就可以通过公有的封装接口访问私有方法。(但此方法背离了OO思想). |
|
在封装私有方法的公有接口上使用[Conditional("DEBUG")] 属性 |
|
创建内部方法访问这些私有方法,并在程序集中其它地方声明一些公有方法封装这些内部方法。 |
|
3. 测试Protected 方法
Protected方法只在派生类可见,因此测试类中不能直接看到。如测试ClassLibrary1.MyObject下面的方法:
protected string MyProtectedMethod(string strInput, int i32Value)
{
return this.Name + ": " + strInput + ", " +
i32Value.ToString();
}
Pragmatic Unit Testing in C# with NUnit 中提供了一个方法,从MyObject派生一个类MyObjectTester,然后建立一个公有方法TestMyProtectedMethod,封装上面的protected方法,如下:
public new string TestMyProtectedMethod(string strInput, int i32Value)
{
return base.MyProtectedMethod(strInput,
i32Value);
}
该方法很简单,满足了上面的所有标准:
标准 |
满足性 |
透明性 |
使用继承将MyObjectTester 类放到UnitTests 程序集中,没有在产品代码中添加新的代码。 |
范围 |
与是否调试模式无关。 |
简单性 |
虽然本方法需要一个继承的类,但符合OO思想。 |
评论