如何对异步 API 进行单元测试? [英] How to unit test asynchronous APIs?
问题描述
我已将 Google Toolbox for Mac 安装到 Xcode 中并遵循设置单元测试的说明位于此处.
I have installed Google Toolbox for Mac into Xcode and followed the instructions to set up unit testing found here.
一切都很好,我可以在我所有的对象上测试我的同步方法绝对没问题.但是,我实际上想通过调用委托上的方法异步测试大多数复杂的 API 返回结果 - 例如,对文件下载和更新系统的调用将立即返回,然后在文件完成下载时运行 -fileDownloadDidComplete: 方法.
It all works great, and I can test my synchronous methods on all my objects absolutely fine. However, most of the complex APIs I actually want to test return results asynchronously via calling a method on a delegate - for example a call to a file download and update system will return immediately and then run a -fileDownloadDidComplete: method when the file finishes downloading.
我将如何将此作为单元测试进行测试?
How would I test this as a unit test?
似乎我想要 testDownload 函数,或者至少让测试框架等待" fileDownloadDidComplete: 方法运行.
It seems like I'd want to the testDownload function, or at least the test framework to 'wait' for fileDownloadDidComplete: method to run.
我现在改用 XCode 内置 XCTest 系统,发现 TVRSMonitor 在 Github 上提供了一种使用信号量等待异步操作完成的简单方法.
I've now switched to using the XCode built-in XCTest system and have found that TVRSMonitor on Github provides a dead easy way to use semaphores to wait for async operations to complete.
例如:
- (void)testLogin {
TRVSMonitor *monitor = [TRVSMonitor monitor];
__block NSString *theToken;
[[Server instance] loginWithUsername:@"foo" password:@"bar"
success:^(NSString *token) {
theToken = token;
[monitor signal];
}
failure:^(NSError *error) {
[monitor signal];
}];
[monitor wait];
XCTAssert(theToken, @"Getting token");
}
推荐答案
我遇到了同样的问题,并找到了适合我的不同解决方案.
I ran into the same question and found a different solution that works for me.
我使用老派"方法通过使用信号量将异步操作转换为同步流,如下所示:
I use the "old school" approach for turning async operations into a sync flow by using a semaphore as follows:
// create the object that will perform an async operation
MyConnection *conn = [MyConnection new];
STAssertNotNil (conn, @"MyConnection init failed");
// create the semaphore and lock it once before we start
// the async operation
NSConditionLock *tl = [NSConditionLock new];
self.theLock = tl;
[tl release];
// start the async operation
self.testState = 0;
[conn doItAsyncWithDelegate:self];
// now lock the semaphore - which will block this thread until
// [self.theLock unlockWithCondition:1] gets invoked
[self.theLock lockWhenCondition:1];
// make sure the async callback did in fact happen by
// checking whether it modified a variable
STAssertTrue (self.testState != 0, @"delegate did not get called");
// we're done
[self.theLock release]; self.theLock = nil;
[conn release];
确保调用
[self.theLock unlockWithCondition:1];
然后在委托中.
这篇关于如何对异步 API 进行单元测试?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!