在 XCTests 中使用 AFHTTPRequestOperation
Posted
技术标签:
【中文标题】在 XCTests 中使用 AFHTTPRequestOperation【英文标题】:Using AFHTTPRequestOperation in XCTests 【发布时间】:2015-01-17 13:26:04 【问题描述】:我有以下测试用例代码:
- (void)testExample
// URL https://api.spotify.com/v1/search?q=album%3AJustified%20artist%3AJustin%20Timberlake&type=album
dispatch_semaphore_t sem = dispatch_semaphore_create(0);
[[AFHTTPRequestOperationManager manager] GET:@"https://api.spotify.com/v1/search"
parameters:@@"q":@"album:Justified artist:Justin Timberlake",
@"type":@"album"
success:^(AFHTTPRequestOperation *operation, id responseObject)
dispatch_semaphore_signal(sem);
failure:^(AFHTTPRequestOperation *operation, NSError *error)
];
dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);
// This is an example of a functional test case.
XCTAssert(YES, @"Pass");
我期待测试用例阻塞并等待 http 请求完成。
奇怪的是,即使 url 是有效的,AFHTTPRequestOperation
也永远不会到达成功块。
如果我在 XCTest 之外使用以下代码,则不会发生,将执行成功块。
有没有人见过这个?
【问题讨论】:
【参考方案1】:几个观察:
您的测试正在冻结,因为 AFNetworking 将其完成块分派到主队列。但是你用dispatch_semaphore_wait
阻塞了主线程,导致死锁。
您可以通过将管理器的completionQueue
设置为用于测试的全局队列来解决此问题,从而消除由主线程上的信号量引起的死锁:
- (void)testExample
dispatch_semaphore_t sem = dispatch_semaphore_create(0);
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
manager.completionQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
[manager GET:@"https://api.spotify.com/v1/search" parameters:@@"q":@"album:Justified artist:Justin Timberlake", @"type":@"album" success:^(AFHTTPRequestOperation *operation, id responseObject)
XCTAssert(YES, @"Pass"); // you might want more rigorous test of results here
dispatch_semaphore_signal(sem);
failure:^(AFHTTPRequestOperation *operation, NSError *error)
XCTFail(@"%@", error.localizedDescription);
dispatch_semaphore_signal(sem);
];
dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);
注意,现在人们会使用XCTestExpectation
来执行异步测试。这消除了对信号量的需求,巧合的是,也解决了死锁问题:
- (void)testExample
XCTestExpectation *expectation = [self expectationWithDescription:@"asynchronous request"];
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
[manager GET:@"https://api.spotify.com/v1/search" parameters:@@"q":@"album:Justified artist:Justin Timberlake", @"type":@"album" success:^(AFHTTPRequestOperation *operation, id responseObject)
XCTAssert(YES, @"Pass"); // you might want more rigorous test of results here
[expectation fulfill];
failure:^(AFHTTPRequestOperation *operation, NSError *error)
XCTFail(@"%@", error.localizedDescription);
[expectation fulfill];
];
[self waitForExpectationsWithTimeout:30.0 handler:nil];
顺便说一句,无论您使用XCTestExpectation
还是信号量,请确保成功和失败块都满足期望/信号量。
【讨论】:
是的,我认为第二种解决方案对我有用。谢谢以上是关于在 XCTests 中使用 AFHTTPRequestOperation的主要内容,如果未能解决你的问题,请参考以下文章