关于OCMock的一些事儿

下载地址:

http://ocmock.org/download/

源码及示例下载地址:

https://github.com/erikdoe/ocmock

项目配置ocmock地址:

http://ocmock.org/ios/

ocmock features:

http://ocmock.org/features/

什么是mock?差不多就是纸老虎


我们写单元测试的时候,不可避免的要去尽可能少的实例化一些具体的组件来保持测试既短又快。而且保持单元的隔离。在现代的面向对象系统中,测试的组件很可
能会有几个依赖的对象。我们用mock来替代实例化具体的依赖class。mock是在测试中的一个伪造的有预定义行为的具体对象的替身对象。被测试的组
件不知道其中的差异!你的组件是在一个更大的系统中被设计的,你可以很有信心的用mock来测试你的组件。

常见的mock使用案例

stub方法

我们用一个简单的例子来开始解释OCMock中一般的stub语法。


1

2

3

id jalopy = [OCMock mockForClass[Car class]];

 [[[jalopy stub] andReturn:@"75kph"] goFaster:[OCMArg any] units:@"kph"];

 // if returning a scalar value, andReturnValue: can be used

OCMock3 新版本对应API


1

2

3

id jalopy = OCMStrictClassMock([Car class]);

OCMStub([jalopy goFaster:[OCMArg any] units:@"kph"]).andReturn(@"75kph");

// if returning a scalar value, andReturnValue: can be used

这个简单的例子首先从Car类中mock出一个jalopy(老爷车),然后,stub掉goFaster:方法让它返回字符串@”75kph”。stub语法可能看起来有点奇怪,但这是普遍的做法:


1

ourMockObject stub] whatItShouldReturn ] method:

OCMock3 新版本对应API


1

OCMStub([ourMockObject method:]).andReturn()

一个非常重要的说明:注意[OCMArg any]的用法。当指定一个带参数的方法时,方法被调用并且参数为指定参数的话,mock会返回andReturn:指定的值。[OCMArg any]方法告诉stub匹配所有的参数值。举个例子:


1

[car goFaster:84 units:@"mph"];

不会触发stub,因为最后一个参数不匹配”kph”.

类方法

OCMock会在mock实例上没有找到相同名字的实例方法的时候去找同名的类方法。在名字相同的情况下(类方法和实例方法同名),用classMethod来指定类方法:


1

[[[[jalopy stub] classMethod] andReturn:@"expired"] checkWarrany];

在OCMock3中classMethod和instanceMethod的stub方式一样,例如:


1

2

3

4

id classMock = OCMClassMock([SomeClass class]);

OCMStub([classMock aClassMethod]).andReturn(@"Test string");

// result is @"Test string"

NSString *result = [SomeClass aClassMethod];

mock类型 – niceMock,partialMock
OCMock提供了几种不同类型的mock,每个都有他们特定的使用场景。

用这种方式来创建任意mock:


1

id mockThing = [OCMock mockForClass[Thing class]];

OCMock3 新版本对应API


1

id mockThing = OCMStrictClassMock([Thing class]);

这就是我所说的‘vanilla’ mock。‘vanilla’ mock当调用一个没有stub的方法的时候会抛出一个异常。这会得到一个单调的mock,且在mock的生命周期中每一个方法调用都要被stub掉。(更多信息请看下一节关于stub)

如果你不想stub很多方法,用‘nice’ mock。‘nice’ mock非常有礼貌而且不会在一个没有stub掉的方法被调用的时候抛出异常。


1

id niceMockThing = [OCMock niceMockForClass[Thing class]];

OCMock3 新版本对应API


1

id mockThing = OCMClassMock([Thing class]);

最后一个mock类型是‘partial’ mock。当一个没有stub掉的方法被调用了,这个方法会被转发到真实的对象上。这是对mock技术上的欺骗,但是非常有用,当有一些类不适合让自己很好的被stub。


1

2

Thing *someThing = [Thing alloc] init];

id aMock = [OCMockObject partialMockForObject:someThing]

OCMock3 新版本对应API


1

2

Thing *someThing = [Thing alloc] init];

id aMock = OCMPartialMock(someThing);

验证方法是否被调用

验证方法是否被调用非常简单。这个可以用expect来完成拒绝和验证方法:


1

2

3

4

id niceMockThing = [OCMock niceMockForClass[Thing class]];

 [[niceMockThing expect] greeting:@"hello"];

 // verify the method was called as expected

 [niceMocking verify];

OCMock3 新版本对应API


1

2

id niceMockThing = OCMClassMock([Thing class]);

OCMVerify([niceMockThing greeting:@"hello"]);


被验证的方法没有被调用的时候会抛出异常。如果你用的是XCTest,那么请用XCTAssertNotThrow来包装验证调用。拒绝方法调用也是同样
的道理,但是会再方法调用的时候抛出异常。就像stub,selector和传递过去验证的参数必须匹配调用时候传递过去的参数。用[OCMArg
any]可以简化我们的工作。

处理block参数

OCMock也可以处理block回调参数。block回调通常用于网络代码,数据库代码,或者在任何异步操作中。在这个例子中,思考下下面的方法:


1

2

- (void)downloadWeatherDataForZip:(NSString *)zip

              callback:(void (^)(NSDictionary *response))callback;

在这个例子中,我们有一个下载天气压缩数据的方法,并且把下载下来的dictionary代理到一个block的回调中。在测试中,我们通过预定义的天气数据来测试回调处理。这也是明智的测试失败场景。你永远不会知道网络上会返回你什么东西!


1

2

3

4

5

6

7

8

9

10

// 1. stub using OCMock andDo: operator.

[[[groupModelMock stub] andDo:^(NSInvocation *invoke) {

        //2. declare a block with same signature

        void (^weatherStubResponse)(NSDictionary *dict);

        //3. link argument 3 with with our block callback

        [invoke getArgument:&weatherStubResponse atIndex:3];

        //4. invoke block with pre-defined input

        NSDictionary *testResponse = @{@"high": 43 , @"low": 12};

        weatherStubResponse(groupMemberMock);

    }][email protected]"80304" callback:[OCMArg any] ];

OCMock3 新版本对应API


1

2

3

4

5

6

7

8

9

10

// 1. stub using OCMock andDo: operator.

OCMStub([groupModelMock downloadWeatherDataForZip:@"80304" callback:[OCMArg any]]]).andDo(^(NSInvocation *invocation){

        //2. declare a block with same signature

        void (^weatherStubResponse)(NSDictionary *dict);

        //3. link argument 3 with with our block callback

        [invoke getArgument:&weatherStubResponse atIndex:3];

        //4. invoke block with pre-defined input

        NSDictionary *testResponse = @{@"high": 43 , @"low": 12};

        weatherStubResponse(groupMemberMock);

    });

这里的大体思想相当简单,即便如此,他的实现也需要一些说明:

1.
这个mock对象使用带NSInvocation参数的“andDo”方法。一个NSInvocation对象代表一个
‘objectivetified’(实在不知道这个什么鬼)表现的方法调用。通过这个NSinvocation对象,使得拦截传递给我们的方法的
block参数变得可能。

2.用与我们测试的方法中相同的方法签名声明一个block参数。

3.NSInvocation实
例方法"getArgument:atIndex:"将赋值后的块函数传递都原始函数中定义的块函数中。注意:在Objective-C中,传递给任意方
法的前两个参数都是“self”和“_cmd”.这是一个运行时的小功能以及用下标来获取NSInvocation参数时我们需要考虑的东西。

4.最后,传递这个回调的预定义字典。

最后

希望这篇文章和例子已经陈述清楚一些OCMock最通用的用法。OCMock站点:http://ocmock.org/features/是一个最好的学习OCMock的地方。mock是单调的但是对于一个现代的OO系统却是必须的。如果一个依赖图很难用mock来测试,这个迹象表明你的设计需要重新考虑了。

转自:http://www.cocoachina.com/ios/20150508/11769.html

时间: 2024-10-06 22:14:40

关于OCMock的一些事儿的相关文章

有些事儿,工程师可能今生仅此一次

郑昀 创建于2016/9/15 最后更新于2016/9/18 关键词:深度思考,碎片化阅读,做论文,深入研究, 早先在<技术高手如何炼成>一文中提到,我会问面试者,你日常如何构建自己的知识体系.有人会觉得你怎么就问出这么宏大的问题?知识体系,这是什么鬼? 面试时的交谈 工作之后你做过这样的事情吗? 面试是一个谁主张谁举证的过程,有时候需要面试者举出实例,自我证明. 而我认为问一些我们工作中遇到的难题和业务场景是在“欺负”面试者,所以我喜欢问开放型问题: 在你工作之后,你有没有像做毕业论文一样对

医疗时鲜(Running)资讯(ZSSURE):移动医疗不算事儿

背景 最近在看Dr.2的书<移动医疗那点事儿>,所以此次博文就厚颜无耻的叫做"移动医疗不算事儿".新的一年,新的积累与进步,继续关注医疗行业的最新动态.此次主要介绍吐槽一下关于"自由执业"和"电子病例"的新闻.Running-- 自由执业 在<移动医疗那点事儿>中,Dr.2开篇问了一个问题"什么样的医生会出来自由执业?刚毕业的孩子会出来自由执业么?",其观点认为:会从体制内出来的医生通常都是一些在临床业

《Java编程那点事儿》读书笔记(七)——多线程

1.继承Thread类 通过编写新的类继承Thread类可以实现多线程,其中线程的代码必须书写在run方法内部或者在run方法内部进行调用. public class NewThread extends Thread { private int ThreadNum; public NewThread(int ThreadNum){ this.ThreadNum = ThreadNum; } public void run(){ try{ for(int i = 0;i < 10;i ++){ T

安装kali之后那些事儿

完全是自己学习后的笔记,和基本的linux配置命令 输入的命令    输入的内容 1.更新软件源:修改sources.list文件: leafpad /etc/apt/sources.list #官方源 deb http://http.kali.org/kali kali main non-free contribdeb-src http://http.kali.org/kali kali main non-free contribdeb http://security.kali.org/kal

XSS与字符编码的那些事儿

目录 0x00:基本介绍 0x01:html实体编码 0x02:新增的实体编码 实体编码变异以及浏览器的某些工作原理! 0x03:javascript编码 0x04:base64编码 0x05:闲扯 0x00基本介绍 提起XSS 想到的就是插入字符字符编码与各种解析了! 这也就是各种xss编码插件跟工具出世的原因!之前不懂浏览器是如何对我们编码过的代码进行解析的时候就是一顿乱插! 各种编码 各种插 没把编码还原就算了 还原了就算运气好!后来到PKAV经过二哥和短短的调教后才算是弄清楚了一点编码与

TCP 的那些事儿(上)

http://coolshell.cn/articles/11564.html TCP是一个巨复杂的协议,因为他要解决很多问题,而这些问题又带出了很多子问题和阴暗面.所以学习TCP本身是个比较痛苦的过程,但对于学习的过程却能让人有很多收获.关于TCP这个协议的细节,我还是推荐你去看W.Richard Stevens的<TCP/IP 详解 卷1:协议>(当然,你也可以去读一下RFC793以及后面N多的RFC).另外,本文我会使用英文术语,这样方便你通过这些英文关键词来查找相关的技术文档. 之所以

【转】 Java 进行 RSA 加解密时不得不考虑到的那些事儿

[转] Java 进行 RSA 加解密时不得不考虑到的那些事儿 1. 加密的系统不要具备解密的功能,否则 RSA 可能不太合适 公钥加密,私钥解密.加密的系统和解密的系统分开部署,加密的系统不应该同时具备解密的功能,这样即使黑客攻破了加密系统,他拿到的也只是一堆无法破解的密文数据.否则的话,你就要考虑你的场景是否有必要用 RSA 了. 2. 可以通过修改生成密钥的长度来调整密文长度 生成密文的长度等于密钥长度.密钥长度越大,生成密文的长度也就越大,加密的速度也就越慢,而密文也就越难被破解掉.著名

MySQL日志审计 帮你揪出内个干坏事儿的小子

MySQL日志审计 帮你揪出内个干坏事的小子 简介 Part1:写在最前 MySQL本身并不像MariaDB和Percona一样提供审计功能,但如果我们想对数据库进行审计,去看是谁把我的数据库数据给删了,该怎么办呢?我们主要利用init-connect参数,让每个登录的用户都记录到我们的数据库中,并抓取其connection_id(),再根据binlog就能够找出谁干了那些破事儿. MariaDB如何审计,可移步: http://suifu.blog.51cto.com/9167728/1857

从街边星探到互联网投资者 龌蹉那些事儿已经没有了?

近几日最热闹的就是支付宝圈子上线大尺度照片引起王思聪回复的话题.就如一夜成名天下知.一夜暴富成土豪的"神话"总是让人向往,而能够快速实现这两个愿望的,似乎也就娱乐圈和互联网两个行业了.相比蹿红.暴富"神话"在几十年内都层出不穷的娱乐圈,互联网在近二十年无疑也更具吸引力.不过需要需要注意的是,在一人蹿红.暴富的背后,隐藏的是太多几经挣扎却默默无闻的人,或者龌龊的事情层出不穷. 不管是此前流行的在街边遇到口吐莲花的星探,还是现在一茬接一茬让无数创业者憧憬其带来融资的投资