我有一个自定义视图控制器,上面有一个按钮,当点击使用AFHTTPRequestOperation异步调用Web服务时,如果请求返回成功,我推送一个uitableviewcontroller。这在设备和模拟器上完美地工作。现在我想写单元测试。我正在运行xcode生成的样本单元测试。在单元测试中,我设法通过sharedapplication.delegate.window.rootviewcontroller获取对我的自定义uiviewcontroller的引用。我可以使用performSelectorOnMainThread调用按钮分接功能,但我的Web服务请求的成功或错误功能不会被触发。我在调用按钮点击事件后调用线程休眠等待仍然没有解雇。我怀疑这是一个线程问题。我该怎么调试呢?
答案 0 :(得分:1)
更好的方法是等待但保持主线程运行。这里有一个很好的例子:
IOS -NSRunLoop in XCTest: How Do I Get A Run Loop to Work in A Unit Test?
当您处理异步完成时设置了某种条件,并设置循环使循环运行循环结束并在满足此条件时继续运行。< / p>
请注意,您可能希望等待异步测试的最长时间。如果您的异步测试永远不会完成(可能底层代码中存在错误),那么您将在测试中遇到死锁,这将是不好的。请注意测试的开始时间,如果您等待的时间超过了开始时间之后的一段时间,则测试失败并继续。
答案 1 :(得分:0)
你是对的,它是一个线程问题。你几乎必须保持你的测试&#34;活着&#34;直到它成功或失败。
以下是我的网络库的单元测试示例。
SomeUnitTest.m
- (void)signalFinished:(NSCondition *)condition
{
[condition lock];
[condition signal];
[condition unlock];
}
#pragma mark - GET
- (void)testGet
{
__block NSCondition *completed = NSCondition.new;
[completed lock];
__weak typeof (self) weakSelf = self;
TSNetworkSuccessBlock successBlock = ^(NSObject *resultObject, NSMutableURLRequest *request, NSURLResponse *response) {
XCTAssertNotNil(resultObject, @"nil result obj");
[weakSelf signalFinished:completed]; //this
};
TSNetworkErrorBlock errorBlock = ^(NSObject *resultObject, NSError *error, NSMutableURLRequest *request, NSURLResponse *response) {
XCTAssertNotNil(error, @"nil error obj");
[weakSelf signalFinished:completed]; //or this will end the test
};
[[TSNetworking sharedSession] setBaseURLString:kNoAuthNeeded];
[[TSNetworking sharedSession] performDataTaskWithRelativePath:@"something"
withMethod:HTTP_METHOD_GET
withParameters:nil
withAddtionalHeaders:nil
withSuccess:successBlock
withError:errorBlock];
[completed waitUntilDate:[NSDate distantFuture]];
[completed unlock];
}