2010-08-13 8 views
0

(C#, Rhino Mocks, MbUnit).Unité testant une méthode sans changement d'état observable

J'ai une classe appelée AccountManager qui a une méthode RegisterUser(). Cette méthode renvoie void mais lance une exception pour les erreurs. AccountManager appelle dans un IDataRepository en appelant sa méthode AddUser() pour effectuer une insertion de base de données.

Je me moque de l'IDataRepository à l'aide d'un Rhino Mock et lance et exception pour un ensemble donné d'arguments simulant l'exception soulevée dans le référentiel.

[Test] 
    public void RegisterKnownUser() 
    { 
     MockRepository mocks = new MockRepository(); 
     IDataRepository dataRepository = mocks.StrictMock<IDataRepository>(); 

     using (mocks.Record()) 
     { 
      Expect.Call(() => dataRepository.AddUser("abc", "abc", "[email protected]", "a", "bc")).Throw(
       new InvalidOperationException()); 
     } 

     using (mocks.Playback()) 
     { 
      AccountManager manager = new AccountManager(dataRepository); 
      Assert.Throws(typeof (InvalidOperationException),() => manager.RegisterUser("abc", "abc", "[email protected]", "a", "bc")); 
     } 
    } 

Ce test fonctionne correctement.

Ma question est quoi faire à propos de la situation où les arguments fournis à RegisterUser sont corrects et valides. Le vrai IDataRepository ne retournerait rien et ne jetterait aucune exception. Donc, en bref, l'état de AccountManager n'aurait pas changé. Cela signifie-t-il que je n'ai pas besoin de tester AccountManager.RegisterUser quand cela ne résulterait en rien que je puisse observer directement dans la classe et la méthode testées. Test contre l'état dans le simulacre sent un peu pour moi. Je pense que tant que je teste IDataRepository.AddUser séparément, je ne devrais pas avoir besoin de tester AccountManager.RegisterUser pour les entrées qui aboutiraient à rien d'observable dans la classe.

Merci d'avance.

+0

Ribgy: Pouvez-vous fournir le code du scénario de test que vous essayez de décrire? AccountManager pourrait-il appeler dans dataRepository? –

Répondre

2

Si AccountManager appelle DataPrepository, votre scénario de test valide quand même quelque chose. L'enregistrement/lecture ici valide qu'un appel est effectué dans celui-ci. Si l'appel n'est pas effectué, le scénario de test échouera. Si elle est faite deux fois/avec les mauvais arguments, elle échouera.

Cela peut être un cas de test très basique, mais il est toujours bon, et ne nécessite pas de placer l'état dans l'objet fantaisie.

+0

Merci (et Main Ma aussi). Je suis allé sur la route de tester l'exception n'est pas jeté pour de bonnes données. –

0

Vous pouvez tester la méthode avec des arguments valides pour vous assurer que ne déclenche aucune exception. En d'autres termes, vous ne pouvez pas observer de changement d'état ou utiliser une valeur de retour (puisqu'il est nul), mais vous pouvez observer que la méthode a été exécutée sans exceptions.

Par ailleurs, si la méthode ne retourne pas de valeur ni changer AccountManager état, cela ne change quelque chose autrement (sinon, que vous devriez probablement retirer de votre code la méthode qui ne rien) .
Par exemple, il peut affecter DataRepository. Ou ajoutez un enregistrement dans la base de données. Dans ce cas, vous pouvez tester au moins si les données sont modifiées ou si l'enregistrement est ajouté avec succès. Ou il peut enregistrer un événement indiquant que le nouvel utilisateur a été enregistré, ainsi vous pourrez, dans vos tests, vérifier si l'événement de journal est ici.

Je pense que tant que je test IDataRepository.AddUser alors je séparement pas besoin de tester AccountManager.RegisterUser pour les entrées qui conduiraient à rien observable dans la classe

Si AccountManager.RegisterUser ajoute rien à IDataRepository.AddUser sauf l'application des arguments, que oui, vous n'avez pas besoin de le tester si vous avez déjà testé IDataRepository.AddUser. S'il vérifie les arguments, appelle AddUseret fait autre chose, il sera bon de vérifier si ce qu'il fait est correct.

Disons que vous avez:

public void AddUser(string userName, string userMail, string passwordHash) 
{ 
    // [...] Add a user to the database. 
} 

public void RegisterUser(string userName, string userMail, string passwordHash) 
{ 
    if (string.IsNullOrEmpty(userName)) throw new ArgumentNullException(...); 
    if (string.IsNullOrEmpty(userMail)) throw new ArgumentNullException(...); 
    if (string.IsNullOrEmpty(passwordHash)) throw new ArgumentNullException(...); 
    if (!Checks.IsValidMail(userMail)) throw new ArgumentException(...); 

    this.AddUser(userName, userMail, passwordHash); 

    this.SaveToLog(LogEvent.UserRegistered, userName, this.IPAddress); 
} 

En RegisterUser, vous tester les quatre premières lignes en passant faux arguments et attend une exception. La cinquième ligne ne doit pas être testée, puisque vous avez déjà testé AddUser. Enfin, la sixième ligne doit être testée pour s'assurer que lorsque vous appelez RegisterUser avec des arguments valides, l'entrée du journal est créée.

Questions connexes