如何在单元测试中将web服务作为uiviewcontroller的一部分来调用?

时间:2014-03-13 04:21:18

标签: ios unit-testing uiviewcontroller performselector

我有一个自定义视图控制器,上面有一个按钮,当点击使用AFHTTPRequestOperation异步调用Web服务时,如果请求返回成功,我推送一个uitableviewcontroller。这在设备和模拟器上完美地工作。现在我想写单元测试。我正在运行xcode生成的样本单元测试。在单元测试中,我设法通过sharedapplication.delegate.window.rootviewcontroller获取对我的自定义uiviewcontroller的引用。我可以使用performSelectorOnMainThread调用按钮分接功能,但我的Web服务请求的成功或错误功能不会被触发。我在调用按钮点击事件后调用线程休眠等待仍然没有解雇。我怀疑这是一个线程问题。我该怎么调试呢?

2 个答案:

答案 0 :(得分:1)

蒂姆的帖子是你需要做的一般想法,但它使主线程死锁,这可能会对某些API造成严重破坏。

更好的方法是等待但保持主线程运行。这里有一个很好的例子:

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];
}