我想單元測試使用XCTest在XCode 5中使用AFNEtworking的類。我遇到的問題是我的AFHTTPRequestOperation的完成塊永遠不會被執行。我認爲這是運行單元測試的XCode和AFNetworking的調度隊列之間的一些斷開。以下測試用例通過,但完成塊中的NSLog語句永遠不會到達(沒有記錄輸出,也沒有捕獲這些語句上設置的斷點)。相同的代碼在單元測試之外工作。有誰知道如何解決這個問題?我使用Nocilla來嘲笑實際的請求,結果是一樣的使用真正的服務器重新調整有效的響應?AFNetworking 2.0和單元測試
編輯,以使測試失敗,並且登錄乏塊設置
- (void)setUp
{
[super setUp];
// Put setup code here. This method is called before the invocation of each test method in the class.
[[LSNocilla sharedInstance] start];
stubRequest(@"POST", @"http://www.example.com/module/api/ping").
andReturn(200).
withHeaders(@{@"Content-Type": @"application/json"}).
withBody(@"{\"success\":true}");
stubRequest(@"GET", @"http://www.example.com/module/api/ping?testkey=testval").
andReturn(200).
withHeaders(@{@"Content-Type": @"application/json"}).
withBody(@"{\"success\":true}");
}
- (void)tearDown
{
// Put teardown code here. This method is called after the invocation of each test method in the class.
[super tearDown];
[[LSNocilla sharedInstance] stop];
[[LSNocilla sharedInstance] clearStubs];
}
- (void)testSanity
{
AFSecurityPolicy *policy = [[AFSecurityPolicy alloc] init];
//[policy setAllowInvalidCertificates:YES];
AFHTTPRequestOperationManager *manager = [[AFHTTPRequestOperationManager alloc] initWithBaseURL:[NSURL URLWithString:@"http://www.example.com/module/api/ping"]];
//manager.operationQueue = [NSOperationQueue mainQueue];
[manager setSecurityPolicy:policy];
manager.requestSerializer = [AFJSONRequestSerializer serializer];
manager.responseSerializer = [AFJSONResponseSerializer serializer];
__block id resObj = nil;
__block id resError = nil;
AFHTTPRequestOperation *req = [manager POST:@"http://www.example.com/module/api/ping"
parameters:[NSDictionary dictionaryWithObject:@"testval" forKey:@"testkey"]
success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(@"Response: %@", responseObject);
resObj = responseObject;
return;
}
failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(@"Error: %@", error);
resError = error;
return;
}];
[req waitUntilFinished];
NSLog(@"req.status: %d", req.response.statusCode);
NSLog(@"req.responseObj: %@", req.responseObject);
XCTAssertTrue(req.isFinished);
NSLog(@"resObj: %@", resObj);
NSLog(@"resError: %@", resError);
XCTAssertEqual([[req.responseObject objectForKey:@"success"] boolValue], YES);
XCTAssertEqual([[resObj objectForKey:@"success"] boolValue], YES);
}
控制檯輸出
Test Case '-[AppSupportTests testSanity]' started. 2014-04-29 16:45:07.424 xctest[72183:303] req.status: 200 2014-04-29 16:45:07.424 xctest[72183:303] req.responseObj: { success = 1; } 2014-04-29 16:45:07.424 xctest[72183:303] resObj: (null) 2014-04-29 16:45:07.425 xctest[72183:303] resError: (null) /Users/jlujan/Code/AppSupport/AppSupportTests/AppSupportTests.m:114: error: -[AppSupportTests testSanity] : (([[resObj objectForKey:@"success"] boolValue]) equal to (__objc_yes)) failed: ("NO") is not equal to ("YES") Test Case '-[AppSupportTests testSanity]' failed (0.003 seconds).
一旦後臺操作完成,它可能調用'waitUntilFinished',但這會在調用回調之前。你可以嘗試使用['semaphore's](https://developer.apple.com/library/ios/documentation/Performance/Reference/GCD_libdispatch_Ref/Reference/reference.html#//apple_ref/doc/uid/TP40008079-CH2 -SW38)改爲[wait](http://goo.gl/lepGmc),直到[有信號](https://developer.apple.com/library/ios/documentation/Performance/Reference/GCD_libdispatch_Ref/Reference/reference .html#// apple_ref/doc/uid/TP40008079-CH2-SW39) – Rich
對於異步測試,我推薦[Expecta](https://github.com/specta/expecta/)。然後你可以做一些類似'expect([[req.responseObject objectForKey:@「success」] boolValue])。will.beTruthy();'(儘管我不喜歡'beTruthy'語法!你只需要確保你設置了一個合適的超時時間[[Expecta setAsynchronousTestTimeout:15]; // seconds' – Rich
這只是一個理智的檢查,以確保我的實際代碼不會導致它。使用這裏的信號量示例http://stackoverflow.com/questions/20476957/afnetworking-2-waituntilfinished-not-working,它永遠掛起。無論哪種方式,我不能在我的實際代碼中使用信號量方法。 – jlujan