Question

Je souhaite tester un élément de code utilisant un réseau (la classe NSURLConnection , pour être spécifique). Le code (appelons-le NetworkManager ) ressemble un peu à ceci:

- (id) buildConnection
{
    // some more code and then:
    return [NSURLConnection …];
}

- (void) startNetworkSync
{
    id connection = [self buildConnection];
    //…
}

Dans le test unitaire, j'aimerais supprimer le réseau, c'est-à-dire. remplacez l'objet NSURLConnection par un faux. Comment je fais ça?

J'ai essayé de créer un modèle partiel de NetworkManager qui remplacerait la méthode buildConnection par un stub. Le problème est que des simulations partielles sont effectuées, comme le fait OCMock , uniquement des messages de bouts provenant du monde extérieur. - l'envoi de buildConnection à partir de startNetworkSync appelle la méthode d'origine, et non le stub.

J'ai également essayé de patcher la classe NetworkManager via une catégorie. Cela fonctionne, je peux facilement remplacer la méthode buildConnection par un autre code et remplacer le réel NSURLConnection par un stub. Le problème est que je n’ai trouvé aucun moyen simple d’obtenir la connexion tronquée dans le test: la connexion est une partie privée du NetworkManager .

Ensuite, je pourrais sous-classer le NetworkManager , remplacer la méthode buildConnection et ajouter une variable d'instance plus un accesseur pour la connexion créée. Cela semble cependant beaucoup de code.

Comment résoudriez-vous cela? Je recherche une solution qui préserve la conception de la classe NetworkManager et n'exige ni beaucoup de magie ni de code dans le test.

Était-ce utile?

La solution

C’est le genre de chose que l’injection de dépendance est conçue pour résoudre; Si vous utilisez startNetworkSyncWithConnection: (NSURLConnection *) , vous pouvez facilement tester la méthode avec une connexion fictive. Si vous ne souhaitez pas modifier l'API de vos clients, vous pouvez même conserver startNetworkSync en tant que wrapper ne faisant qu'appeler cette nouvelle méthode avec [self buildConnection] en tant que argument.

Autres conseils

J'ai modifié OCMock pour prendre en charge les simulacres partiels réels, voir le rapport sur GitHub .

Une autre solution que j'ai récemment utilisée consiste à résumer complètement l'interface réseau. Si la classe a besoin de données du réseau, elle interagit probablement avec un service de serveur pouvant être explicitement modélisé comme un protocole:

@protocol SomeNetworkService
- (NSArray*) allAvailableFoos;
- (void) insertNewFoo: (Foo*) foo;
@end

Ensuite, vous aurez une implémentation HTTP réelle et une version de test. Cela signifie plus de travail, mais aussi une bien meilleure testabilité. Les tests sont moins fragiles et beaucoup plus pratiques, car la couche réseau de test peut faire tout ce dont vous avez besoin.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top