在Objective-C中对协议/回调/委托进行OCUnit测试

时间:2009-07-03 04:14:49

标签: objective-c unit-testing delegates ocunit

使用OCUnit,有没有办法测试委托协议?

我正在尝试这个,这不起作用。

-(void) testSomeObjDelegate {
  SomeObj obj = [[SomeObj alloc] initWithDelegate:self];
  [obj executeMethod];
}
-(void) someObjDelegateMethod {
  //test something here
}

我将尝试在不同的线程上调用obj方法,并让测试进入睡眠状态,直到调用委托。看起来似乎应该有一种更简单的方法来测试它。

2 个答案:

答案 0 :(得分:53)

测试委托是微不足道的。只需在回调方法中在测试中设置一个ivar,并在触发委托回调之后检查它。

例如,如果我有一个使用协议Something委托的课程SomethingDelegate并发送该委托-something:delegateInvoked:以回复某些消息,我可以测试它的喜好:< / p>

@interface TestSomeBehavior : SenTestCase <SomethingDelegate>
{
    Something *_object;
    BOOL _callbackInvoked;
}
@end

@implementation TestSomeBehavior

- (void)setUp {
    [super setUp];
    _object = [[Something alloc] init];
    _object.delegate = self;
}

- (void)tearDown {
    _object.delegate = nil;
    [_object release];
    [super tearDown];
}

- (void)testSomeBehaviorCallingBack {
    [_object doSomethingThatShouldCallBack];

    STAssertTrue(_callbackInvoked,
                 @"Delegate should send -something:delegateInvoked:");
}

- (void)something:(Something *)something delegateInvoked:(BOOL)invoked {
    _callbackInvoked = YES;
}

@end

但是,我认为你已经从你提出问题的方式中理解了这一点。 (我主要是为其他读者发布这个。)我认为你实际上是在问一个更微妙的问题:我如何测试可能会在以后出现的东西,例如旋转runloop的东西。我的暗示是你提到睡眠和穿线。

首先,你不应该只是在另一个线程上任意调用一个方法。只有在记录下以这种方式安全使用时才应该这样做。原因是你不知道班上的内部是做什么的。例如,它可能在运行循环上调度事件,在这种情况下,在不同的线程上运行该方法将使它们在不同的运行循环上发生。这会搞砸班级的内部状态。

如果您执行需要测试可能需要一些时间的事情,您可以通过运行当前的运行循环来执行此操作。以下是我可以重写上面的单个测试方法来做到这一点:

- (void)testSomeBehaviorCallingBack {
    NSDate *fiveSecondsFromNow = [NSDate dateWithTimeIntervalSinceNow:5.0];

    [_object doSomethingThatShouldCallBack];

    [[NSRunLoop currentRunLoop] runUntilDate:fiveSecondsFromNow];

    STAssertTrue(_callbackInvoked,
                 @"Delegate should send -something:delegateInvoked:");
}

这将在默认模式下将当前运行循环旋转5秒,假设-doSomethingThatShouldCallBack将在默认模式下在主运行循环上调度其工作。这通常是正常的,因为以这种方式工作的API通常允许您指定要使用的运行循环以及要运行的模式。如果可以这样做,那么您可以使用-[NSRunLoop runMode:beforeDate:]来运行运行循环相反,这种模式使你更有可能完成你期望完成的工作。

答案 1 :(得分:12)

请查看Unit Testing Asynchronous Network Access。我想可以帮到你。 简而言之,它的作用是:

  

添加以下方法来处理同步   单元测试代码和被测异步代码之间:

- (BOOL)waitForCompletion:(NSTimeInterval)timeoutSecs {
    NSDate *timeoutDate = [NSDate dateWithTimeIntervalSinceNow:timeoutSecs];

    do {
        [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:timeoutDate];
        if([timeoutDate timeIntervalSinceNow] < 0.0)
            break;
    } while (!done);

    return done;
}