Ich versuche Unit-Test eine Klasse, die AFNEtworking in XCode 5 mit XCTest verwendet. Das Problem, das ich habe, ist, dass die Abschlussblöcke für meine AFHTTPRequestOperation nie ausgeführt werden. Ich nehme an, das ist eine Trennung zwischen XCode, der den Komponententest ausführt, und AFNetworking's Dispatch Queue. Der folgende Testfall besteht, aber die NSLog-Anweisungen in den Completion-Blöcken werden nie erreicht (keine Protokollausgabe und keine in diesen Anweisungen gesetzten Haltepunkte werden abgefangen). Derselbe Code funktioniert außerhalb eines Komponententests. Kann jemand dieses Problem umgehen? Ich benutze Nocilla, um die tatsächlichen Anfragen zu verspotten, das Ergebnis ist das gleiche mit einem echten Server, der gültige Antworten neu einleitet?AFNetworking 2.0 und Komponententest
Edited machen Test nicht und melden Sie sich vars
- (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);
}
Konsolenausgabe
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).
Es ruft wahrscheinlich 'waitUntilFinished 'auf, sobald die Hintergrundoperation beendet ist, aber dies wäre bevor die Callbacks aufgerufen werden. Sie könnten versuchen, ['semaphore's] (https://developer.apple.com/library/ios/documentation/Performance/Reference/GCD_libdispatch_Ref/Reference/reference.html#//apple_ref/doc/uid/TP40008079-CH2 zu verwenden -SW38) bis [warten] (http://goo.gl/lepGmc), bis Sie [signiert] haben (https://developer.apple.com/library/ios/documentation/Performance/Reference/GCD_libdispatch_Ref/Reference/reference .html # // apple_ref/doc/uid/TP40008079-CH2-SW39) – Rich
Für asynchrone Tests empfehle ich übrigens [Expecta] (https://github.com/specta/expecta/). Sie können dann Sachen wie 'expect ([[req.responseObject objectForKey: @" Erfolg "] boolValue]). Will.beTruthy();' machen (obwohl ich nicht auf die 'beTruthy'-Syntax scharf bin!). Sie müssen nur sicherstellen, dass Sie ein passendes Zeitlimit setzen '[Expecta setAsynchronousTestTimeout: 15]; // Sekunden' – Rich
Dies war nur eine Plausibilitätsprüfung, um sicherzustellen, dass mein tatsächlicher Code dies nicht verursachte. Unter Verwendung des Semaphorbeispiels hier http://stackoverflow.com/questions/20476957/afnetworking-2-waituntilfinished-not-working, hängt es für immer. In beiden Fällen kann ich die Semaphor-Methode in meinem eigentlichen Code nicht verwenden. – jlujan