最近工作上的活就是研究一下如何为一个历史代码工程添加单元测试,已经做完了,就想抛砖引玉和大家分享一下结果,听听大家的反馈。
该工程目前还是VS2010下的C#代码,虽然大量使用了继承,封装和多态,但对接口的应用非常少,所以基本上没办法用常见的Mock框架(如Moq, Rhino Mock,等)来写单元测试。
考虑下来,解决方案无非两种:一是重构现有代码,通过接口(interface)来实现依赖注入(Dependency Injection, DI);二是寻找无需通过接口直接支持虚拟实体类的Mock框架,用来拦截对依赖对象的访问,返回预定的结果。采用方案一的话,优化了代码架构,从长远来说更好一些,但是工作量较大,还需要做大量的测试以保证不会改变现有代码功能。采用方案二的话,则不需要对现有代码做任何改动,只需要直接创建测试代码就好了。因此方案二还是很有吸引力的,我就按这个方向做了一些研究。
我发现市面上暂时还没有开源的Mock框架(.NET单元测试相关)支持虚拟实体类,而收费的我也只找到Microsoft Fakes, TypeMock Isolator和Telerik JustMock这三个。三者虽然用法上有些差异,但是主要功能比较接近,差别主要体现在以下几个方面:
1.从价格上来看:
Microsoft Fakes,没有免费版,只有在VS2012/VS2013的Premium和Ultimate版中才能用,而我们的开发环境用的主要是Professional版的,升级到相应版本的话成本很高(VS2013的话Windows Store差价$1770,MSDN Subscription差价$4920)
Telerik JustMock满足需求的版本价格是每个开发者$399,包含一年免费升级+支持,(参见Buy JustMock)
TypeMock Isolator满足需求的版本价格是$799每个license,$150每年升级+支持,(参见Isolator Pricing)
由于Fakes价格太高,而且还需要升级现有代码,我们直接就不考虑了。当然如果已经在用相应版本的话,还是可以考虑的,毕竟微软自己的东西还是用起来最方便的。
2.从功能上看,根据我们的一个测试用例分别用TypeMock和JustMock试写了一下,发现JustMock更强大一些。
我们的这个测试用例是要测某个时间值由于特殊原因不包含年份,因此从客户端传到位于不同时区的服务端时,在跨年时会被解析到错误的年份。比如:客户端位于GMT+8在2014/01/01 07:00:00时传了01/01 07:00:00过来,而服务端位于GMT,当时是2013/12/31 23:00:00,这个时间就会被解析成2013/01/01 07:00:00。解析调用的是DateTime.ParseExact()方法。TypeMock对MSCorLib中类的虚拟只提供了有限的支持,不支持这个方法的虚拟。而JustMock在这方面则做得好一些,能够支持该方法。
所以,我的最终结论是要么重构代码,使用接口来实现依赖注入,那么基本上各种Mock框架都能用;要么就买JustMock,不用动现有代码,直接加单元测试就好了。
最新内容请见作者的GitHub页:http://qaseven.github.io/