DotNetMock源代码解析

 

DotNetMock源代码解析<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

 

DotNetMock库是我们使用较多的Mock库之一,目前已经能够支持NunitMBunit,CSUnit等多个测试框架,结合这些测试框架,能够非常方便的测试那些不太方便创建的对象、或者该对象具有比较复杂的不太确定的行为的对象。该框架也被许多开源的框架所使用,为此我门简单的分析了它的源代码,大致搞清楚它的实现过程。

 

Mock的基本原理

类图

<?xml:namespace prefix = v ns = "urn:schemas-microsoft-com:vml" />

11.JPG
每个需要
Mock的类都需要实现IMockObject或者从MockObject继承。

MockObject及其之类的对象掉用Verify时,将调用Verfier.Verify(),该函数首先取得检查对象的父对象,进行检查,然后检查每个Field,代码如下:

private static void verify(Object verifiableObject, Type currentType)

        {

            if (isRootType(currentType))

            {

                return;

            }

 

            verify(verifiableObject, currentType.BaseType);

 

            FieldInfo[] fields = currentType.GetFields(_bindingFlags);

            ///检查每个Field

            foreach (FieldInfo field in fields)

            {

                verifyField(field, verifiableObject);

            }

            ///将已经检查过的对象记入已检查对象列表。

            _verifiedObjects.Add( verifiableObject.GetHashCode() );

        }

isRootType:如果为类型为Object时,到达根对象,就不用再检查了。

检查某个Field时,如果该Field也是可检查对象,则检查,否则不做检查,代码如下:

Private static void verifyField(FieldInfo verifiableField, Object verifiableObject)

        {

            Object fieldValue = verifiableField.GetValue(verifiableObject);

           

            IVerifiable aVerifiable;

            if ((aVerifiable = fieldValue as IVerifiable) != null)

            {

                if ( ! aVerifiable.IsVerified )

                {

                    aVerifiable.Verify();

                }

            }

        }

代码aVerifiable.Verify()循环上面的调用过程。

测试框架支持

       这部分比较复杂,大致思路是这样子,当你需要判断期望的值与执行后的值是否相等时,在NUnit中可以使用Assertion.AssertEquals(“”,ExpectionValue,ActualValue),而在MBUnit中没有直接对应的方法,为此我们需要先定义一个接口,然后针对不同的测试框架实现这个接口,为了避免直接和框架耦合,可以使用配置文件,通过Assembly.Load 等方式加载这个框架。这个方法就是DotNetMock使用的框架静态加载机制。

       DotNetMock没有为我们提供这些框架的加载代码,可能DotnetMock的作者认为太简单了,并且为每个框架只作一个Assembly实在很丑陋,为此他又提供了一个动态机制来自动生成一个动态的Assembly,这种方法使用了MSIL的高级方法,基本的原理图如下:

 12.JPG

其中,ITestFramework抽象了测试框架的行为,如:NUnitMbUnit等,通过Assertion来调用该框架,Assertion就是测试框架在DotNetMock中的代言人。Assertion使用Implementation来获得一个ITestFramework的实例,Implementation使用ImplementationFactory来加载这个实例,而ImplementationFactory首先通过配置文件,获取是否静态实现了ITestFramework,记载该静态的Assembly,否则通过动态机制先获得使用哪种测试框架(作者在这里使用判断方式,判断当前AppDomain域里面加载了哪个测试框架,如果加载了多个,按照优先级NunitMbunitCSUnit进行判断,判断接收后,分别创建对应的StubMaker对象,这个对象负责创建相应的实现代码),然后调用StubClassMaker来创建一个Assembly,通过SystemDynamicLinkerIDynamicLinker的实现)来加载该Assembly

动态Mock

       使用静态Mock的机制我们就已经能够建立Mock对象并进行测试了,这意味着我们要编写一个接口,一个实现该接口的Mock类,这样导致单元测试的代码量过于庞大。为此我们一般将静态Mock用于实现测试用的Mock框架,如:数据库测试用的Mock框架、安全测试用的Mock框架等,DotNetMock提供了一个这样的框架。

       为了解决上述问题,DotNetMock提供了动态Mock机制,这意味着我们编写单元测试代码时,只需要提供接口,不需要编写测试用的Mock代码。

类图

  13.JPG
    
当我们通过IDynamicMock dynamicMockObjectnew DynamicMock(typeof(我们的接口));系统会自动调用ClassGenerator生成一个动态的Assembly,并生成一个“mock我们的接口”的实现类。通过IMyInterface myInstancemock.object来获得该实现类的一个对象,使用myInstance,通过使用mock.SetValue(方法名称,)来设置Mock对象中,某个方法的返回值。当我们调用该接口的方法时,DotNetMock会自动产生一个ExpectionMethod并使用MethodCall调用返回刚才设置的值。基本原理图如下:

 

14.JPG      

       由于方法调用本身比较复杂,可能使用表达式方式调用,如:isReadOnly && IsCanAccess,首先要通过断言的Eval来判断参数是否与设置的值是否相等,从来进行调用。这一部分没有进行仔细研究,如有问题请及时反馈给我。

15.JPG
由于时间仓促,有些部分没有仔细研究,如果大家发现什么问题请及时反馈:
caidehui@21cn.com 或者QQ19646007 .

转载于:https://www.cnblogs.com/caidehui/archive/2005/10/11/dotnetmock.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值