6

我在测试一些使用通知的逻辑时遇到了困难。我已经阅读了有关强制NSNotifications发送特定内容的信息,但这并不能真正解决我所看到的问题。

[SomeObject PerformAsyncOperation]创建一个NSURLRequest并将自己设置为响应委托。根据响应的内容,将SomeObject成功或失败发布NSNotification到默认值NSNotificationCenter

我的测试的问题是,在PerformAsyncOperation调用之后,测试不会等待发送响应。相反,它继续断言 - 失败,因为请求/响应没有时间发送/接收/解析。

这是代码:

-(void)testMethod {
    SomeObject *x = [[SomeObject alloc] init];

    [[NSNotificationCenter defaultCenter] addObserver:self
                                        selector:@selector(success:)
                                            name:SomeObjectSuccess
                                          object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self
                                        selector:@selector(failure:)
                                            name:SomeObjectFailure
                                          object:nil];

    operationCompleted = false; // declared in .h

    [x PerformAsyncOperation:@"parameter"];

    STAssertTrue(operationCompleted , @"Operation has completed.");

    [[NSNotificationCenter defaultCenter] removeObserver:self name:SomeObjectSuccess object:nil];
    [[NSNotificationCenter defaultCenter] removeObserver:self name:SomeObjectFailure object:nil];

    [x release];
}

-(void) failure:(NSNotification *) notification {
   operationCompleted = true;
   NSLog(@"Received failure message.");
}

-(void) success:(NSNotification *) notification {
   operationCompleted = true;
   NSLog(@"Received success message.");
}

我已经尝试在调用后使线程休眠PerformAsyncOperation,以及一个空while (!operationCompleted)循环。两者都不起作用 - 休眠线程仍然使断言失败,并且 while 循环永远不会退出。我也尝试将断言移入success:and failure:,但是因为 OCUnit 期望每个方法都是测试方法,所以它只是立即执行所有三个方法并退出(不等待NSURLRequest' 的响应,这就是练习的重点! )。

任何想法或见解将不胜感激。谢谢!

4

2 回答 2

15

您面临的问题不是通知,而是同步的。相反,您正在触发异步操作。要使这是一个可重复的测试,您需要重新同步事物。

NSTimeInterval timeout = 2.0;   // Number of seconds before giving up
NSTimeInterval idle = 0.01;     // Number of seconds to pause within loop
BOOL timedOut = NO;

NSDate *timeoutDate = [[NSDate alloc] initWithTimeIntervalSinceNow:timeout];
while (!timedOut && !operationCompleted)
{
    NSDate *tick = [[NSDate alloc] initWithTimeIntervalSinceNow:idle];
    [[NSRunLoop currentRunLoop] runUntilDate:tick];
    timedOut = ([tick compare:timeoutDate] == NSOrderedDescending);
    [tick release];
}
[timeoutDate release];

超过这一点,您就知道操作已完成,或者测试已超时。

于 2011-06-03T05:28:07.390 回答
0

为简单起见,如果可能,请使用同步网络请求。

- (void)testExample
{
    [self measureBlock:^{

        NSURLRequest *request = [[NSURLRequest alloc] initWith...];

        NSHTTPURLResponse *response = nil;
        NSData *data = [NSURLConnection sendSynchronousRequest:request
                                         returningResponse:&response
                                                     error:nil];

        XCTAssertEqual(response.statusCode,200);

        // process the data from response ... call the delegate methods or whatever

        NSObject *object = [NSJSONSerialization JSONObjectWithData:data
                                                       options:NSJSONReadingMutableContainers
                                                         error:nil];
        XCTAssertTrue([object isKindOfClass:[NSArray class]]);
    }];
}
于 2015-06-11T09:08:45.007 回答