Unit-Tests mit NSURLConnection
-
03-07-2019 - |
Frage
Ich mag ein Stück Code zu testen, das Netzwerk verwendet (die NSURLConnection
Klasse, um genau zu sein). Der Code (nennen wir es NetworkManager
) sieht ein bisschen wie folgt aus:
- (id) buildConnection
{
// some more code and then:
return [NSURLConnection …];
}
- (void) startNetworkSync
{
id connection = [self buildConnection];
//…
}
In dem Unit-Test würde Ich mag an der Vernetzung, um loszuwerden, das heißt. die NSURLConnection
Aufgabe durch ein mock ersetzen. Wie mache ich das?
Ich habe versucht, eine partielle Mock des NetworkManager
zu schaffen, die die buildConnection
Methode durch einen Stub ersetzen würde. Das Problem ist, dass teilweise Mocks als getan von OCMock nur Stub-Nachrichten von der Außenwelt -. buildConnection
vom startNetworkSync
Senden der ursprünglichen Methode aufruft, nicht die Stub
Ich habe auch versucht, Affen-Patchen die NetworkManager
Klasse durch eine Kategorie. Dies funktioniert, kann ich leicht die buildConnection
Methode von anderen Code überschreiben und die reale NSURLConnection
mit einem Stummel ersetzen. Das Problem ist, dass ich keine einfache Art und Weise fand ich die gekürzte Verbindung im Test bekommen konnte -. Die Verbindung ist ein privater Teil der NetworkManager
Dann könnte ich die NetworkManager
Unterklasse, die buildConnection
Methode außer Kraft setzen und eine Instanzvariable und einen Accessor für die erstellte Verbindung hinzufügen. Dies scheint eine Menge Code, though.
Wie würden Sie dieses Problem lösen? Ich bin auf der Suche nach einer Lösung, die NetworkManager
Klasse Design sauber hält und nicht viel Magie noch viel Code im Test erforderlich ist.
Lösung
Dies ist die Art von Dingen, Dependency Injection ist so konzipiert, zu lösen; wenn Sie startNetworkSyncWithConnection:(NSURLConnection*)
verwenden stattdessen können Sie einfach die Methode mit einer Mock-Verbindung testen. Wenn Sie möchten, dass das API für Ihre Kunden nicht ändern könnten Sie sogar startNetworkSync
als Wrapper halten, die nichts tun, sondern dass die neue Methode mit [self buildConnection]
als Argument nennen.
Andere Tipps
I modifizierte OCMock zu echten Teil Mocks zu unterstützen, finden Sie die Repo auf GitHub rel="nofollow.
Eine andere Lösung, die ich vor kurzem verwendet haben, ist völlig abstrakt die Netzwerkschnittstelle. Wenn die Klasse einige Daten aus dem Netzwerk benötigt, es interagiert wahrscheinlich mit einem Server-Dienst, explictly als Protokoll modelliert werden kann:
@protocol SomeNetworkService
- (NSArray*) allAvailableFoos;
- (void) insertNewFoo: (Foo*) foo;
@end
Und dann werden Sie eine echte HTTP-Implementierung und eine Prüfung ein. Das bedeutet mehr Arbeit, aber auch viel besser Testbarkeit. Die Tests sind weniger spröde und viel bequemer, da die Testnetzwerkschicht tun, was Sie benötigen.