Protected方法与单元测试
创始人
2024-05-07 15:10:58
0

本篇文章讨论了protected方法的测试和Mock,以及其中需要注意的一些可测试性的方面。这是一篇简单的文章,讨论了单元测试中遇到protected成员的应对方案。此外,在文章最后也希望和大家讨论一下某个特殊的情况下的处理方法。

protected是一个有趣而有用的修饰符,它把方法的访问成员严格限制在自身或自己的子类身上。换句话说,在使用过程中,protected成员对外部是开放的(因为其他类可以通过继承来使用该成员),又是封闭的(不是自身或子类的一切成员都无法访问)。而对于单元测试来说,protected成员又是尴尬的,因为它的“开放”意味着我们必须对它进行单元测试,而“封闭”又阻碍了我们在单元测试中涉及protected成员。

测试protected方法

现在有一个类,其中包含一个protected方法:

  1. public class SomeClass  
  2. {  
  3.     protected int SomeMethod(string arg) { ... }  

如果我们需要对这个protected方法进行单元测试,可以在测试代码中准备一个辅助类型:

  1. public class SomeClassForTest : SomeClass  
  2. {  
  3.     public int PublicSomeMethod(string arg)  
  4.     {  
  5.         return this.SomeMethod(arg);  
  6.     }  

于是在单元测试中,便可以通过调用PublicSomeMethod来测试基类的SomeMethod方法:

  1. var testClass = new SomeClassForTest();  
  2. var result = testClass.PublicSomeMethod(null);  
  3. Assert.Equal(0, result); 

非常简单。

如果您觉得麻烦,也可以将SomeClass类中的SomeMethod方法改为protected internal,这样便可以在InternalVisibleTo的测试程序集中使用了。不过,我觉得为单元测试而改变成员的访问级别不是一个合适的做法。

对protected方法进行Mock

现在有一个类,其中有一个protected方法:

  1. public class SomeClass  
  2. {  
  3.     protected virtual int SomeMethod(string arg) { ... }  

并且,某个被测试的方法接受SomeClass作为参数。虽然被测试的方法不会直接调用SomeMethod方法,但是SomeMethod的实现会影响到公开接口的表现形式。于是,我们需要对SomeMethod进行Mock或Stub。为此,我们同样需要准备一个辅助类型:

  1. public class MockSomeClass : SomeClass  
  2. {  
  3.     protected override int SomeMethod(string arg)  
  4.     {  
  5.         return this.PublicSomeMethod(arg);  
  6.     }  
  7.  
  8.     public virtual int PublicSomeMethod(string arg)  
  9.     {  
  10.         return base.SomeMethod(arg);  
  11.     }  
  12. }  

在MockSomeClass中,我们覆盖了基类的SomeMethod实现,使它调用了子类中公开的PublicSomeMethod方法,而PublicSomeMethod内部又调用了基类的SomeMethod方法。因此,如果您不去进行任何处理,那么MockSomeClass会保持SomeMethod的实现不变。而如果您需要对SomeMethod进行Mock或Stub的时候,便可以从PublicSomeMethod下手:

  1. Mock mockSomeClass = new Mock() { CallBase = true };  
  2. mockSomeClass.Setup(c => c.PublicSomeMethod("123")).Returns(123);  
  3.  
  4. DoSomeTest(mockSomeClass.Object); // use the mock object  

也很容易。

为了可测试性

值得注意的是,为了“可测试性”,第二部分中的protected方法必须是virtual的,因为我们需要在子类中进行override。同理,Mock框架能够辅助的方法也必须是virtual的,即使是一个public方法。那么,您觉得这是为了可测试性而做出的让步吗?或者换句话说,您觉得,一个不可以override的protected方法,但是会影响到其他公开接口的功能,这是不是一个合理的设计呢?如果这是一个合理的设计,又不想作出这样的让步……我们又该怎么做呢?

本文来自老赵点滴:《与protected成员有关的单元测试方式》

【编辑推荐】

  1. 开发人员最欠缺哪些测试知识?
  2. 编程对软件测试人员意味着什么?
  3. 使用JBPM工作流引擎测试的一个例子
  4. 软件测试项目的启动、规划与需求分析
  5. 伟大骡子的一生和性能测试

相关内容

热门资讯

如何允许远程连接到MySQL数... [[277004]]【51CTO.com快译】默认情况下,MySQL服务器仅侦听来自localhos...
如何利用交换机和端口设置来管理... 在网络管理中,总是有些人让管理员头疼。下面我们就将介绍一下一个网管员利用交换机以及端口设置等来进行D...
施耐德电气数据中心整体解决方案... 近日,全球能效管理专家施耐德电气正式启动大型体验活动“能效中国行——2012卡车巡展”,作为该活动的...
Windows恶意软件20年“... 在Windows的早期年代,病毒游走于系统之间,偶尔删除文件(但被删除的文件几乎都是可恢复的),并弹...
20个非常棒的扁平设计免费资源 Apple设备的平面图标PSD免费平板UI 平板UI套件24平图标Freen平板UI套件PSD径向平...
德国电信门户网站可实时显示全球... 德国电信周三推出一个门户网站,直观地实时提供其安装在全球各地的传感器网络检测到的网络攻击状况。该网站...
着眼MAC地址,解救无法享受D... 在安装了DHCP服务器的局域网环境中,每一台工作站在上网之前,都要先从DHCP服务器那里享受到地址动...
为啥国人偏爱 Mybatis,... 关于 SQL 和 ORM 的争论,永远都不会终止,我也一直在思考这个问题。昨天又跟群里的小伙伴进行...