2009-03-30 5 views
22

Ich schreibe eine iPhone-Anwendung, die einige Daten von einem Webserver erhalten muss. Ich verwende NSURLConnection, um die HTTP-Anfrage auszuführen, was gut funktioniert, aber ich habe Schwierigkeiten, meinen Code zu testen, wenn die Antwort einen HTTP-Fehlercode hat (wie 404 oder 500).Testen der Verwendung von NSURLConnection mit HTTP-Antwort Fehlerstatus

Ich verwende GTM für Unit-Tests und OCMock für Spott.

Wenn der Server einen Fehler zurückgibt, wird die Verbindung nicht nennen connection:didFailWithError: auf den Delegaten, fordert jedoch connection:didReceiveResponse:, connection:didReceiveData: und connectionDidFinishLoading: statt. Ich überprüfe gerade den Statuscode auf der Antwort in connection:didReceiveResponse: und rufe cancel auf der Verbindung auf, wenn der Statuscode wie ein Fehler aussieht, um zu verhindern, dass connectionDidFinishLoading: aufgerufen wird, wo eine erfolgreiche Antwort gemeldet würde.

Die Bereitstellung eines statischen Stubs NSURLConnection ist einfach, aber ich möchte, dass mein Test das Verhalten ändert, wenn eine der Methoden der Scheinverbindung aufgerufen wird. Insbesondere möchte ich, dass der Test in der Lage ist zu sagen, wann der Code cancel auf der Scheinverbindung aufgerufen hat, so dass der Test connection:didReceiveData: und connectionDidFinishLoading: auf dem Delegaten nicht mehr aufrufen kann.

Gibt es eine Möglichkeit für Tests, ob cancel für das Mock-Objekt aufgerufen wurde? Gibt es eine bessere Möglichkeit, Code zu testen, der NSURLConnection verwendet? Gibt es eine bessere Möglichkeit, HTTP-Fehlerstatus zu behandeln?

+0

Würde es Ihnen etwas ausmachen, einen Beispielcode zu zeigen, wie Sie die Aufrufe von NSURLConnection testen? –

Antwort

43

Is there a better way to handle HTTP error statuses?

Ich denke, Sie sind auf dem richtigen Weg. Ich verwende etwas ähnlich dem folgenden Code, der ich here gefunden:

if ([response respondsToSelector:@selector(statusCode)]) 
{ 
    int statusCode = [((NSHTTPURLResponse *)response) statusCode]; 
    if (statusCode >= 400) 
    { 
     [connection cancel]; // stop connecting; no more delegate messages 
     NSDictionary *errorInfo 
      = [NSDictionary dictionaryWithObject:[NSString stringWithFormat: 
      NSLocalizedString(@"Server returned status code %d",@""), 
      statusCode] 
             forKey:NSLocalizedDescriptionKey]; 
     NSError *statusError 
      = [NSError errorWithDomain:NSHTTPPropertyStatusCodeKey 
           code:statusCode 
          userInfo:errorInfo]; 
     [self connection:connection didFailWithError:statusError]; 
    } 
} 

Bricht die Verbindung und ruft connection:didFailWithError:, um genau das gleiche wie jeder andere Verbindungsfehler verhalten Codes http Fehler zu machen.

+1

Funktioniert gut. Kleines Problem: 'NSHTTPPropertyStatusCodeKey' ist veraltet. –

+3

Sie können eine beliebige Zeichenfolge verwenden, z. B. @ "Error" anstelle von NSHTTPPropertyStatusCodeKey –

+0

Ja, dies sieht nicht wie eine korrekte Verwendung von 'NSHTTPPropertyStatusCodeKey' aus. Vgl. die NSURL-Klassenreferenz: http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSURL_Class/Reference/Reference.html%23//apple_ref/occ/instm/NSURL/relativePath . Wenn Sie Xcode 4.4 oder höher verwenden, können Sie den Wörterbuchcode wahrscheinlich auf '@ {NSLocalizedDescriptionKey: [NSHTTPURLResponse localizedStringForStatusCode: statusCode]}' verkürzen. –