2009-09-06 5 views
1

Avertissement: C'est la première fois que j'écris des tests unitaires ... soyez doux! :)Suis-je tester la bonne chose ... vos pensées s'il vous plaît!

J'essaie d'écrire un test pour la méthode suivante et aimerais que les gens pensent si je pense à la bonne façon. J'ai une interface appelée IAuthenticationProvider avec la méthode suivante:

bool Authenticate(string username, string password) 

J'ai aussi une classe appelée UserAccountService qui a la méthode suivante:

bool SignIn(string username, string password) 

Le UserAccountService prend une interface IAuthenticationProvider dans le cadre du constructeur et est utilisé dans la méthode SignIn. La méthode SignIn ressemble un peu:

public bool SignIn(string username, string password) 
{ 
    // _provider is of type IAuthenticationProvider 
    bool result = _provider.Authenticate(username, password); 
    // .... 
    return result; 
} 

Au départ, quand je pensais à des tests tels que « la signature avec le nom d'utilisateur inconnu », « la signature avec un mot de passe non valide », etc. Mais, je puis commencé à penser que Je ne veux pas vraiment tester l'aspect "authentification", c'est-à-dire _provider.Authenticate, mais je veux tester la connexion réelle. Donc, je pensais à des tests tels que "signer en étant déjà connecté", "signer quand le l'utilisateur ne peut pas être authentifié ", etc, aurait plus de sens.

Serait-ce la bonne façon d'aborder ce genre de tests?

Cordialement

Michael

+0

Je ne pense pas que ce soit une bonne pratique d'utiliser CapitalizedNames pour les méthodes. Juste une pensée. –

+0

Je pense que c'est C#. –

+0

@Stefano: Il s'agit presque certainement de C#, auquel cas il est recommandé d'utiliser CamelCase. – Noldorin

Répondre

2

Vous pouvez utiliser un test simulé. Cela mettrait en place un UserAccountService avec une mise en œuvre fictive de IAuthenticationProvider.

//happy case provider return true 
mock = createMock(IAuthenticationProvider, true); 
service = new UserAccountService(mock).SignIn(..); 
... 

//provider will return false 
mock = createMock(IAuthenticationProvider, false); 
service = new UserAccountService(mock).SignIn(..); 
... 

Vous pouvez écrire vos propres implémentations fictives si vous le souhaitez. La plupart du temps, il est plus facile d'utiliser une bibliothèque maquette comme easymock:

//same as above 
mock = createMock(IAuthenticationProvider.class) 
expect(mock.Authenticate(...)).andReturn(true); 
replay(mock) 
service = new UserAccountService(mock).SignIn(..); 
//test here 

des tests simulés ont leur propre coût et ne devraient être utilisés lors d'un test basé sur l'état est impossible. Votre conception d'application doit être telle que les classes dépendent du moins de classes possible et puissent idéalement travailler seules (plus votre temps d'exécution).

+0

J'aime l'idée d'utiliser un cadre de moquerie et de garder le test de «l'authentification» ailleurs. Je vais essayer cette approche. –

+0

Je n'utilise généralement pas d'objet Mock. J'utilise un objet réel chaque fois que c'est possible. Si vous modifiez l'implémentation de IAuthenticationProvider un jour, vous devrez vérifier et modifier tous vos cas de test utilisant un objet fantaisie. Vous devez vous assurer que l'objet fantaisie que vous avez créé reflète la fonctionnalité de l'objet réel. Quel cauchemar d'entretien. – janetsmith

+0

Si vous regardez cet exemple, vous verrez que l'objet fantaisie dépend de l'interface et non de l'implémentation de cette interface. Le faux doit seulement être capable de reproduire cela. Cela ne dépend pas de la connaissance de l'implémentation quand accepter. La maquette doit changer lorsque le contrat d'interface change. –

1

Vous tester l'authentification dans les tests pour la classe IAuthenticationProvider. Cela est supposé fonctionner. Dans SignIn(), vous devez considérer le _provider comme parfait (tout problème sera testé ailleurs dans votre suite de tests) et tester la routine SignIn. Toutefois, vous devez également tester tout ce qui a été testé pour IAuthProvider sur la méthode SignIn. Cela vous donnera une couverture supplémentaire pour que vos informations soient correctement transmises à _provider, et que leur résultat soit correctement renvoyé.

+2

Simple ou pas la mise en œuvre pourrait être: public bool SignIn (nom d'utilisateur chaîne, mot de passe string) {return true} et tous vos tests sont toujours heureux. Mon treshold de choses que je ne pense pas cassables descend constamment. :-) –

+0

Je pense que vous avez raison :) –

+0

Serait-il réellement possible, ou nécessaire, d'effectuer à nouveau les tests IAuthProvider dans la méthode SignIn? La méthode SignIn ne s'intéresse vraiment qu'aux valeurs true/false possibles de la méthode Authenticate. –

0

Je reconnais que vous ne devriez pas tester l'authentification dans SignIn, car cela se passe réellement dans le fournisseur. Si tout ce que la méthode SignIn fait est ce qui est montré ci-dessus, renvoyer le résultat de _provider.Authenticate, alors les seuls tests qui ont un sens pour cette méthode particulière sont plutôt triviaux, pour vérifier que ça retourne False pour un False de _provider.Authenticate et True pour un True de _provider.Authenticate. Passez dans les fournisseurs fictifs avec des résultats connus au constructeur pour le test.Si "se connecter alors que vous êtes déjà connecté" et "vous connecter lorsque l'utilisateur ne peut pas être authentifié" est traité dans votre méthode SignIn mais pas montré ci-dessus, alors oui, il est logique de le tester ici. Mais pas si elles sont faites ailleurs. Pour les tests unitaires, vous voulez seulement tester ce que l'unité particulière est responsable.

Questions connexes