验证延迟和拒绝需要花费大量时间来运行测试

时间:2014-10-15 09:10:08

标签: ocmock

我的项目使用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];
}

在拒绝注册的地方,“期望”变量总是包含那些拒绝,因此等待所有延迟时间。

有人有同样的问题吗? 也许我做错了什么,这是正确的行为?

1 个答案:

答案 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];

}