我的项目使用OCMock,OHHTTPStubs和XCTest。 我尝试测试SDK(由我实现的SDK),所以我存根Http响应/请求并在回调方法上添加一些期望。每个单元测试都有一些期望,即委托方法将被正确调用,并且在设置所有期望之后,我包括每个委托方法的拒绝,以确保只调用指定的方法,而不再是。
我的单元测试示例:
// stub http
... here are some http stubs...
// expect
[[self.mockDelegate expect] didSomethigHappend:[OCMArg checkWithBlock:^BOOL(id obj) {
BOOL result = NO;
// testing parameter object
if(result) {
// call next method on SDK
[self.objectToTest nextMethod];
}
return result;
}] withError:[OCMArg isNil]];
// reject any other call:
[[self.mockDelegate reject] didSomethigHappend:[OCMArg any] withError:[OCMArg any]];
[[self.mockDelegate reject] dodSomethig2:[OCMArg any] withError:[OCMArg any]];
[[self.mockDelegate reject] dodSomethig3:[OCMArg any] withError:[OCMArg any]];
[super.objectToTest doSomethigWithDelegate:super.mockDelegate]; // run
[super.mockDelegate verifyWithDelay:3]; // verify
所有测试都成功通过,但运行所有内容需要花费大量时间。但是我所看到的,当我删除那些拒绝时,所有测试运行速度提高了3倍。 经过一些调试后,我检查了OCMock库方法的实现:
- (void)verifyWithDelay:(NSTimeInterval)delay atLocation:(OCMLocation *)location
{
NSTimeInterval step = 0.01;
while(delay > 0)
{
if([expectations count] == 0)
break;
[[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:step]];
delay -= step;
step *= 2;
}
[self verifyAtLocation:location];
}
在拒绝注册的地方,“期望”变量总是包含那些拒绝,因此等待所有延迟时间。
有人有同样的问题吗? 也许我做错了什么,这是正确的行为?
答案 0 :(得分:0)
它表明OCMock有一个错误。
以下是方法调配的解决方法:
// stubbing verify with delay from ocmock framework
// because ocmock if has any registered rejects
// waits whole specified time, so we need to change this flow
// so it will wait for all expectation has occure and after that wait some steps to make sure that any reject has not invoked
static dispatch_once_t swizzle_token;
dispatch_once(&swizzle_token, ^{
SEL originalSelector = @selector(verifyWithDelay:);
SEL swizzledSelector = @selector(fake_verifyWithDelay:);
Method originalMethod = class_getInstanceMethod([OCMockObject class], originalSelector);
Method swizzledMethod = class_getInstanceMethod([VDFUsersServiceBaseTestCase class], swizzledSelector);
BOOL didAddMethod =
class_addMethod([OCMockObject class],
originalSelector,
method_getImplementation(swizzledMethod),
method_getTypeEncoding(swizzledMethod));
if (didAddMethod) {
class_replaceMethod([OCMockObject class],
swizzledSelector,
method_getImplementation(originalMethod),
method_getTypeEncoding(originalMethod));
} else {
method_exchangeImplementations(originalMethod, swizzledMethod);
}
});
这是fake_verify方法:
- (void)fake_verifyWithDelay:(NSTimeInterval)delay {
NSTimeInterval step = 0.1;
while (delay > 0) {
@try {
[self verify];
break;
}
@catch (NSException *e) {}
[[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:step]];
delay -= step;
step += 0.1;
}
[self verify];
}