我似乎无法弄清楚如何测试这种方法:
- (void)writer:(id)writer didFailWithError:(NSError *)error;
{
[self.alertView dismissWithClickedButtonIndex:0 animated:YES];
void (^alertViewBlock)(int) = ^(int buttonIndex)
{
if (buttonIndex == 1)
{
[self performSelectorOnMainThread:@selector(savePostponeReasonsAsynchronously) withObject:nil waitUntilDone:NO];
}
else
{
NSLog(@"dismissed");
self.savePostponeReasonsQueue = nil;
}
};
[self showPostponeReasonFailedAlert:alertViewBlock];
}
具体如何测试调用选择器savePostponeReasonsAsynchronously?
感谢
答案 0 :(得分:3)
测试异步方法调用的一种方法是等待它们完成:
__block BOOL isRunning = YES;
[[[myPartialMock expect] andDo:^(NSInvocation *invocation){ isRunning = NO; }] savePostponeReasonsAsynchronously];
myPartialMock writer:nil didFailWithError:nil;
NSDate *timeout = [NSDate dateWithTimeIntervalSinceNow:10];
do {
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode
beforeDate:timeout];
} while (isRunning);
STAssertFalse(isRunning, @"Test timed out.");
[myPartialMock verify];
这是我通过观察Rob Napier的test code for RNCryptor学到的一种技术,它也有一些使用信号量的好技巧。
答案 1 :(得分:0)
我写了一个实现“承诺”的库。事实证明,这个概念不仅可用于解决复杂的异步问题,还可用于测试:
假设您有一些异步方法,并想检查是否将调用完成处理程序,以及它是否返回预期结果。作为奖励,您还需要设置测试人员等待完成处理程序的超时。如果它到期,测试应该失败。
通用完成处理程序块:
typedef void (^completion_block_t)(id result);
你的testie,一个可能基于循环运行的异步方法:
- (void) asyncFooWithCompletion:(completion_block_t)completionHandler;
您的测试可能如下所示:
- (void) testAsyncFooWithCompletion
{
// Your test - executing on the main thread.
RXPromise* handlerPromise = [RXPromise new];
[foo asyncFooWithCompletion:^(id result){
// possibly perform assertions
...
if (result is expected) {
// expected in this test scenario
// resolve promise with a value indicating success:
[handlerPromise fulfillWithValue:@"OK"];
}
else {
// unexpected in this test scenario
// resolve promise with an error:
[handlerPromise rejectWithReason:@"Unexpected result"];
}
}];
注意:asyncFooWithCompletion:
的工作负载可以在运行循环上进行调度,该运行循环在相应的线程上执行 - 例如主线。
完成处理程序也可以在同一个运行循环上执行,例如在主线上。
// Set a timeout. If the timeout expires before the handler get called,
// the promise will be resolved with a "timeout error":
[handlerPromise setTimeout:5.0];
// Register handlers, which get called when _handlerPromise_ will be resolved.
// We did perform a all assertions in the completion handler. Thus here,
// just catch unexpected failures - including a timeout:
[handlerPromise.thenOn(dispatch_get_main_queue(), nil,
^id(NSError* error) {
// We are on the main thread
ADD_FAILURE() << [[error description] UTF8String];
return error;
})
runLoopWait]; // wait on the current run loop.
// if we reach here, assertions have been executed (on the main thread)
// and all handlers have been returned.
} // end test