OCMock使用技巧

最近在写OC的单元测试,虽然XCTest已经越来越好了,但是对mock的支持还是欠缺很多。所以上网查了下,发现多说OCMock不错,去官网看了看,第一眼看过去主页做的很好看,主页做的好的开源团队一般东西都不会差,赶紧用起来。

配置OCMock

这个官网上有详细的步骤教程,按着做就好了。贴个连接http://ocmock.org/ios/

开始mock

1. mock方法返回值

mock方法返回值这个应该是最常用的一种情况了,也是非常简单的一种情况。示例代码如下:

id mockClass = OCMClassMock([SomeClass class]);
//没有参数的方法
OCMStub([mockClass someMethod]).andReturn(anObject);
//有参数的方法
OCMStub([mockClass someMethod:[OCMArg any]]).andReturn(anObject);

这里需要注意的就是有参数的方法,参数是可以具体指定的,也就是说只有满足你指定的具体参数的调用才会被mock指定的返回值。例子中的[OCMArg any]是指任意参数。

2. 验证mock方法被调用

有些时候需要验证我们执行的代码流程是否调用了某个外部的方法,这个时候用OCMock就比较简单来实现。

id mockClass = OCMClassMock([SomeClass class]);
//...
//some code
//...
OCMVerify([mockClass someMethod]);

如果没有调用过这个方法的话,会立即抛一个异常出来。

3. 验证mock方法没有被调用

而有些时候呢,我们想要验证代码没有调用某个方法,这里因为OCMock对这种情况没有支持,我也查阅了很多资料,最后想出了一个比较取巧的办法,但还算有效。

static BOOL isCalled = false;
id mockClass = OCMClassMock([SomeClass class]);
OCMStub([mockClass someMethod]).andDo(^(NSInvocation *invocation){
isCalled = YES;
});
//...
//some code
//...
XCTAssertFalse(isCalled);

如果方法被调用了,就将isCalled设置为YES,这样最后assert的时候就会报错。

4. 验证mock方法传入的参数

还有的情况需要验证传递给外部调用的参数是否符合预期,示例代码:

id mockClass = OCMClassMock([SomeClass class]);
OCMStub([mockClass someMethod:[OCMArg checkWithBlock:^BOOL(id obj) {
//...
//some code
//...
return YES;
]]);

5. mock单例

如果我们mock的类是个单例的话,那么使用之前的方法进行mock是不会生效的。不过OCMock提供了一个很简单的解决方法,那就是调用单例返回mock。

id mockClass = OCMClassMock([SomeClass class]);
OCMStub([mockClass instanceMethod]).andReturn(mockClass);

这样之后,我们就可以正常的进行mock了。