正文

如何测试私有/受保护的方法? (译文) (一)2010-07-21 10:31:00

【评论】 【打印】 【字体: 】 本文链接:http://blog.pfan.cn/edwardguo/51517.html

分享到:

       1.   简介     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思想). 这种方法只能在调试模式有效。 过程式而非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思想。

阅读(2805) | 评论(0)


版权声明:编程爱好者网站为此博客服务提供商,如本文牵涉到版权问题,编程爱好者网站不承担相关责任,如有版权问题请直接与本文作者联系解决。谢谢!

评论

暂无评论
您需要登录后才能评论,请 登录 或者 注册