测试委托是微不足道的。只需在回调方法的测试中设置一个 ivar,并在应该触发委托回调之后检查它。
例如,如果我有一个Something
使用协议委托的类SomethingDelegate
并发送该委托-something:delegateInvoked:
以响应某些消息,我可以像这样测试它:
@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
但是,我认为您已经从您提出问题的方式中理解了这一点。(我主要是为其他读者发布此内容。)我认为您实际上是在问一个更微妙的问题:我如何测试以后可能发生的事情,例如旋转运行循环的事情。我的暗示是你提到的睡眠和穿线。
首先,您不应该随意调用另一个线程上的方法。只有当它被记录为可以安全使用时,您才应该这样做。原因是你不知道类的内部是做什么的。例如,它可能会在运行循环上安排事件,在这种情况下,在不同的线程上运行该方法将使它们发生在不同的运行循环上。这会搞砸类的内部状态。
如果您确实需要测试可能需要一些时间才能发生的事情,您可以通过运行当前的运行循环来做到这一点。以下是我如何重写上面的单个测试方法来做到这一点:
- (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:]
仅在该模式下运行运行循环,使您期望完成的工作更有可能完成。