手头的项目越来越大,很多以前不会出现的问题开始浮现。
比如:我修改了一个基础的类库,却意外的影响了九重天外的客户项目,直接导致一个功能无法实现。我郁闷啊!!!
因此开始要有组织、有预谋、有计划的对项目过程进行测试驱动了。最终目标是,我修改了底层某个dll的某个方法,测试框架能够自动帮我找出来所有收到影响的类,全部执行一次回归测试,并发送一份漂亮的报告到我手里。
这个目标估计1、2个星期才能实现,不过现在先放出一个非常漂亮的MOCK核心代码。
研究过程
在不断收集各种资料过程中,学习了很多,例如以下关键字,有兴趣的兄弟可以自己搜索一下:
testdriven.net, nunit, typemock, cruiseControl.net, Confluence, JIRE, NUnitForms, WatiN, MBUnit, CSUnit, NBehave, Gallio
ranorex, dynamicProxy...
估计各位有时间看看上面的简介,就能够掌握现在测试驱动的大致发展。
- nunit的核心代码非常容易理解,大伙自己下载看看就行了。
- testdriven.net 的前身是:NUnitAddin, 如果要研究如何testdriven集成到vs,看看不错。
- WatiN的核心代码虽然我没有看,不过猜也能猜到,就是调用了IE的核,然后搜索上面的html标签操作。
- typeMock有点混蛋,源码混淆了,无法拿到核心技术,不过从介绍来看是源自了castle.DynamicProxy,那么各位可以参观一下一篇非常垃圾的文章,但是起码让我入门了:http://www.cublog.cn/u/23701/showart_1414436.html
- 最后,我来到了Moq,开始因为听说是.net3.5,就没有看源码,不过刚才研究了一下顿时非常兴奋。起码Moq能让我解决了50%的工作。
接下来就说下Mock技术和测试驱动中的作用。
Mock技术
我最不喜欢老外造名词,所以会用自己的体会去介绍。
mock的本质就是模拟目标对象的一个假对象。
这个性质在测试驱动中非常有用,例如我的代码是:
代码
publicDateTimeGetNextFiredDate(DateTimenow,IOrmScheduleTriggertrigger,inttriggeredtimes)
{
returnGetNextFiredDate(now,trigger.TriggerType,trigger.TriggerExpression,triggeredtimes);
}
现在要测试这个代码,就需要传入一个IOrmScheduleTrrigger的接口对象。但是不幸的是,这个对象是个ORM,要启动这个对象,就涉及到了数据库。。。。
老大,我只是想测试一下一辆宝马的玻璃是否坚硬,不需要启动我的宝马加速到120km,然后再用手去翘翘那块玻璃吧。
所以,我希望能够有个模拟对象,继承了这个接口, 同时提供了我期望的返回值,让这个方法能够顺利执行。
传统的傻逼方法,就是自己写一个类,继承了这个接口,然后才传入进去。例如:
publicclassOrmScheduleTriggerTestObject:IOrmScheduleTrigger
{
//somemethodhere
}
这样不就更加的傻逼了?我为了测一块玻璃,还亲自造了另外一台简易的宝马出来? 于是我开始翻阅各种文献,甚至考虑使用动态代理(DynamicProxy)。动态代理的核心思想就是在代码运行中写IL生成一个继承类。这个技术很有用,但是现在我还用不上(就像martin fowler说的,typemock就等于把交给了一个4岁小孩)。
于是我继续寻找,终于翻开了Moq的源码,找到了答案。
先看看以下一段代码,是我摘自Moq源码的核心部分,稍加改造了:
代码
usingSystem;
usingSystem.Collections.Generic;
usingSystem.Text;
usingSystem.Runtime.Remoting.Proxies;
usingSystem.Runtime.Remoting.Messaging;
namespacePixysoft.Framework.TestDrivens
{
publicclassMock<TInterface>:RealProxy
{
publicMock()
:base(typeof(TInterface))
{
}
publicTInterfaceValue
{
get
{
return(TInterface)this.GetTransparentProxy();
}
}
publicoverrideIMessageInvoke(IMessagemsg)
{
IMethodCallMessagemethodCall=msgasIMethodCallMessage;
//我返回int=1
returnnewReturnMessage(1,null,0,null,methodCall);
}
}
publicinterfaceIMock
{
intDevide(inta,intb);
}
publicclasstestrealproxy//测试代码在这里!!!
{
publicvoidtest()
{
IMockmock=newMock<IMock>().Value;
Console.WriteLine(mock.Devide(1,2));
//输出=1
}
}
}
这段代码就是Moq的核心思想。
大概意思是:我希望调用接口IMock的方法Devide,但是我压根不想写这个接口的实现。
那么我先写一个通用的模拟对象Mock<TInterface>,继承了RealProxy。
然后通过调用Value就可以返回需要的接口对象。而这个对象就是return (TInterface)this.GetTransparentProxy();是个透明代理。
最后当我调用了int Devide(int a, int b); 方法的时候,等于调用了public override IMessage Invoke(IMessage msg)方法(有点点的AOP感觉)。
后记
上文就是Moq的核心思想了。非常的精彩!估计有了思路,各位就可以制造自己的原子弹了。
这里插句题外话,很多人抨击重复造轮子。我就奇怪了。如果我造一个轮子花费的时间和学习用一个轮子的时间差不远,为什么不造一个?
而且,用别人的轮子,经常出现的情况是:很多轮子不知道挑哪个。一旦挑上了,项目进展到一般才发现不适合、有bug,于是又重头挑另外的轮子。
这个经历是真实的。当年读大学,我的室友就是典型的挑轮子,他懂得很多框架(java),webwork,hibernate, spring。和人砍起来朗朗上口,但是需要深入做项目了,出现问题基本上不知所措,不是翻文献,就是问师兄,最后整个项目组从来就没有一个成品。
我自从学电脑依赖,从来就没有用过别人的轮子,即使是hibernate,我的确也没有用过,不过他的核心文档倒是看过,对比之下,和oracle的toplink相比简直就是小孩。
比我牛逼的兄弟大有人在,希望各位牛人不要浪费自己的时间去挑别人的轮子,直接自己造一个算了。
最后说说接下来的工作。
基于接口的测试驱动完成了,剩下的就是面对sealed class 等顽固分子了, 必然需要动用非常规武器,DynamicProxy。下回再见。
分享到:
相关推荐
mock测试实战
mock练习
在java web应用中,通过mock技术可以模拟spring容器,从而进行单元测试,详细可以参见本文
本书手把手教你从头开始开发一个真正的Web应用,并且展示使用Python做测试驱动开发(TDD)的优势。你将学到如何在开发应用的每一个部分之前先编写和运行测试,然后再编写最少量的代码让测试通过。也就是说,你将学会...
Mock模拟测试,定义、好处、关键点、Mockito使用、Mock 对象的行为验证、Spy 对象验证等
单元测试高级特性--mock模拟网络请求单元测试高级特性--mock模拟网络请求单元测试高级特性--mock模拟网络请求单元测试高级特性--mock模拟网络请求单元测试高级特性--mock模拟网络请求单元测试高级特性--mock模拟网络...
服务端Mock测试
SpringBoot 集成的单元测试,代码优化过程中都会使用的技术;MockBean和SpyBean实现单元测试的需求
仿百度地图搜索查询框+mock数据基本展示+ js触发mark定位。
可以用来Mock JAVA代码中的静态方法
iview.test测试demo包含拖拽排序 mock测试 iview模板...
支持http接口自由mock,可根据需要进行接口mock测试。
关于test的mock技术 可以入门,而且是很好的学习资料
mock struts1 测试
8-Mock技术实战-2021.01.25.pdf
在window或者linux上,模拟一个mock接口,可以实现等同的接口效果,本人测试过
HTTP模拟测试服务器 MockServer ,MockServer 是一个 API ,建华了通过 HTTP 集成(服务、web网站等)的系统的模拟...
NULL 博文链接:https://username2.iteye.com/blog/1812762
并有详细的代码示例、异常测试的概念的测试代码、 超时测试的概念及测试代码、忽略测试的概念及测试代码、Mock学习及前后端代码调试、Mockito基本使用方法简介、MockMVC基于RESTful风格的测试、Mock.js基本简介、...
而测试驱动开发(TDD)更进一步将mock作为一种设计手段,来辅助识别出元素之间交 mock在单元测试中已经众所周知。现今我们有各种功能强大而又好用的mock框架,可以很方便的解除单元测试中各种依赖,这大大的降低了...