在 上一篇中已经介绍了GHUnit。GHUnit和OCUnit使用上基本上一致,但是他提供了更多的feature。同时,结果展示上更友好。
不管是系统自带的OCUnit还是GHUnit,基本上都不支持Mock,OCMock就是一个开源的ObjC的Mock库。很多时候,GHUnit和OCMock经常一起使用的。
首先我们先来了解下OCMock库。
OcMock 官方网站:http://ocmock.org/
OCMock是为了某些不容易构造或者不用一获取的对象,用一个虚拟的对象来创建以便测试。可以虚拟返回,虚拟调用等。接下来我们看看OCMock到底是个什么东东。
类Mock:创建一个类的Mock 对象
id mock = [OCMockObject mockForClass:[SomeClass class]]
期望(expect)和验证(verify)
[[mock expect] someMethod:someArgument]
[mock verify]
mock 对象的指定方法指定参数的函数被调用。mock Verify 后 相当于 Mock的 Class 的实例instance调用了
[instance someMethod:someArgument].
很简单,对吧。不过mock主要还是用到stub模式,相当于创建了一个类的虚拟实例。基于这个实例我们可以:
[[[mock stub] andReturn:aValue] someMethod:someArgument]
// 调用指定方法,指定参数,并返回固定值 aValue;
[[[mock stub] andReturnValue:OCMOCK_VALUE((BOOL){YES})] someMethod:someArgument]
// 同上,返回OCMock定义的数据类型 BOOL
[[mock stub] someMethodWithReferenceArgument:[OCMArg setTo:anObject]
// 指定一个对象最为参数,并执行somemethod
[[mock stub] someMethodWithReferenceArgument:[OCMArg setToValue:OCMOCK_VALUE((int){aValue})
// 同上
[[[mock stub] andThrow:anException] someMethod:someArgument]
//调用方法,并抛出指定异常
[[[mock stub] andPost:aNotification] someMethod:someArgument]
//调用方法,并发送一个通知
[[[[mock stub] andPost:aNotification] andReturn:aValue] someMethod:someArgument]
//调用方法,结束后返回一个aValue并同时发送一个Notication。
[[[mock stub] andCall:@selector(aMethod:) onObject:anObject] someMethod:someArgument]
//同上,由notificaiton变为直接执行某个方法
void (^theBlock)(NSInvocation *) = ^(NSInvocation *invocation) {
/* code that reads and modifies the invocation object */
};
[[[mock stub] andDo:theBlock] someMethod:[OCMArg any]];
// 调用方法后,异步执行一个Block
[[[mock expect] andForwardToRealObject] someMethod]
基于参数的mock:
[[mock expect] someMethodWithPointerArgument:[OCMArg anyPointer]]
[[mock expect] someMethod:[OCMArg isNil]]
[[mock expect] someMethod:[OCMArg isNotNil]]
[[mock expect] someMethod:[OCMArg isNotEqual:aValue]]
[[mock expect] someMethod:[OCMArg checkWithSelector:aSelector onObject:anObject]]
[[mock expect] someMethod:[OCMArg checkWithBlock:^BOOL(id value) { /* return YES if value is ok */ }]];
[[mock expect] someMethod:startsWith(@"foo")]
基于参数主要是为了解决一些边界测试,测试API的接口健壮性。
OCMock也支持 Protocol的mock
id aMock = [OCMockObject mockForProtocol:@protocol(SomeProtocol)]
OCMock还支持实例化后对象的Mock
id aMock = [OCMockObject partialMockForObject:anObject]
Observer模式的Mock
id aMock = [OCMockObject observerMock]
[notificatonCenter addMockObserver:aMock name:SomeNotification object:nil]
[[mock expect] notificationWithName:SomeNotification object:[OCMArg any]]
更多关于OCMock的知识请参考官网,最好结合例子看。
OCMock的集成很简单。IOS上是通过静态库的方式。将.a文件和相应的.h文件加入工程设置中。同时添加other link flag:
本篇完,下一节我通过一个例子来展示GHUnit和OCMock