最近在写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了。