Méthodes de test des unités vides?

Quelle est la meilleure façon de tester une méthode qui ne renvoie rien? Spécifiquement en c #.

Ce que j’essaie vraiment de tester est une méthode qui prend un fichier journal et l’parsing pour des chaînes spécifiques. Les chaînes sont ensuite insérées dans une firebase database. Rien de ce qui n’a pas été fait auparavant mais étant TRÈS nouveau sur TDD, je me demande s’il est possible de le tester ou si c’est quelque chose qui n’est pas vraiment testé.

Si une méthode ne renvoie rien, c’est l’un des suivants:

  • impératif – Vous êtes soit en train de demander à l’object de faire quelque chose pour lui-même .. par exemple changer l’état (sans attendre de confirmation .. c’est supposé être fait)
  • informationnel – notifier simplement à quelqu’un que quelque chose s’est passé (sans attendre d’action ou de réponse) respectivement.

Méthodes impératives – vous pouvez vérifier si la tâche a bien été effectuée. Vérifiez si le changement d’état a bien eu lieu. par exemple

void DeductFromBalance( dAmount ) 

peut être testé en vérifiant si le solde après ce message est effectivement inférieur à la valeur initiale par dAmount

Méthodes d’information – sont rares en tant que membre de l’interface publique de l’object … et ne sont donc pas normalement testées par unité. Toutefois, si vous devez, vous pouvez vérifier si la manipulation à effectuer lors d’une notification a lieu. par exemple

 void OnAccountDebit( dAmount ) // emails account holder with info 

peut être testé en vérifiant si l’e-mail est envoyé

Publiez plus de détails sur votre méthode actuelle et les gens pourront mieux répondre.
Mise à jour : Votre méthode fait 2 choses. Je l’ai divisé en deux méthodes qui peuvent maintenant être testées indépendamment.

 ssortingng[] ExamineLogFileForX( ssortingng sFileName ); void InsertSsortingngsIntoDatabase( ssortingng[] ); 

Ssortingng [] peut être facilement vérifié en fournissant la première méthode avec un fichier factice et les chaînes attendues. Le second est un peu délicat .. vous pouvez soit utiliser un Mock (google ou search stackoverflow sur des frameworks moqueurs) pour imiter la firebase database ou bash la firebase database réelle et vérifier si les chaînes ont été insérées au bon endroit. Vérifiez ce fil pour quelques bons livres … Je recommanderais Pragmatic Unit Testing si vous êtes dans une impasse.
Dans le code, il serait utilisé comme

 InsertSsortingngsIntoDatabase( ExamineLogFileForX( "c:\OMG.log" ) ); 

Testez ses effets secondaires. Ceci comprend:

  • Est-ce qu’il jette des exceptions? (Si c’est le cas, vérifiez que c’est le cas. Si ce n’est pas le cas, essayez des cas en coin qui pourraient être si vous ne faites pas attention – les arguments null étant la chose la plus évidente.)
  • Est-ce qu’il joue bien avec ses parameters? (S’ils sont mutables, les transforme-t-il quand ils ne devraient pas et inversement?)
  • A-t-il le bon effet sur l’état de l’object / du type sur lequel vous l’appelez?

Bien sûr, il y a une limite à ce que vous pouvez tester. Vous ne pouvez généralement pas tester avec toutes les entrées possibles, par exemple. Testez de manière pragmatique, de manière à vous donner l’assurance que votre code est conçu de manière appropriée et correctement implémenté, et suffisamment pour agir en tant que documentation supplémentaire sur les attentes d’un appelant.

Comme toujours: testez ce que la méthode est censée faire!

Devrait-il changer d’état global (uuh, odeur de code!) Quelque part?

Faut-il appeler une interface?

Doit-il lancer une exception lorsqu’il est appelé avec les mauvais parameters?

Ne devrait-il pas faire exception lorsqu’il est appelé avec les bons parameters?

Devrait-il …?

Les types de retour annulés / les sous-routines sont une vieille nouvelle. Je n’ai pas fait un type de retour annulé (à moins d’être extrêmement paresseux) pendant environ 8 ans (à partir du moment de cette réponse, donc juste un peu avant que cette question ne soit posée).

Au lieu d’une méthode comme:

 public void SendEmailToCustomer() 

Faites une méthode qui suit le paradigme de Microsoft int.TryParse ():

 public bool TrySendEmailToCustomer() 

Peut-être n’y a-t-il aucune information que votre méthode doit renvoyer pour une utilisation à long terme, mais le fait de renvoyer l’état de la méthode après l’exécution de son travail est très utile pour l’appelant.

De plus, bool n’est pas le seul type d’état. Il y a un certain nombre de fois où un sous-programme précédemment fait pourrait retourner trois états différents ou plus (bon, normal, mauvais, etc.). Dans ces cas, vous utiliseriez simplement

 public StateEnum TrySendEmailToCustomer() 

Cependant, même si le Try-Paradigm répond quelque peu à cette question sur la manière de tester un retour de compte, il existe d’autres considérations également. Par exemple, pendant / après un cycle “TDD”, vous seriez “Refactoring” et notez que vous faites deux choses avec votre méthode … brisant ainsi le “principe de responsabilité unique”. Donc, cela devrait être pris en compte en premier. Deuxièmement, vous avez peut-être identifié une dépendance… vous touchez des données «persistantes».

Si vous effectuez les opérations d’access aux données dans la méthode en question, vous devez les restructurer en une architecture n-tiers ou n-couche. Mais nous pouvons supposer que lorsque vous dites “les chaînes sont ensuite insérées dans une firebase database”, vous voulez dire que vous appelez une couche de logique métier ou quelque chose du genre. Ya, nous allons assumer cela.

Lorsque votre object est instancié, vous comprenez maintenant que votre object a des dépendances. C’est à ce moment que vous devez décider si vous allez faire l’dependency injections sur l’object ou sur la méthode. Cela signifie que votre constructeur ou la méthode en question nécessite un nouveau paramètre:

 public  (IBusinessDataEtc otherLayerOrTierObject, ssortingng[] stuffToInsert) 

Maintenant que vous pouvez accepter une interface de votre object d’entreprise / de données, vous pouvez la simuler lors des tests unitaires et ne pas avoir de dépendance ou de crainte de tests d’intégration “accidentels”.

Donc, dans votre code live, vous passez un object REAL IBusinessDataEtc . Mais dans votre test unitaire, vous passez un object MOCK IBusinessDataEtc . Dans cette maquette, vous pouvez inclure des propriétés non-interface comme int XMethodWasCalledCount ou quelque chose dont l’état est mis à jour lorsque les méthodes d’interface sont appelées.

Ainsi, votre test unitaire passera par votre méthode (s) -In-Question, exécutera la logique qu’il a et appelle un ou deux, ou un ensemble de méthodes sélectionné dans votre object IBusinessDataEtc . Lorsque vous faites vos assertions à la fin de votre test unitaire, vous avez plusieurs choses à tester maintenant.

  1. L’état de la “sous-routine” qui est maintenant une méthode Try-Paradigm.
  2. L’état de votre object Mock IBusinessDataEtc .

Pour plus d’informations sur les idées d’dependency injections au niveau de la construction … en ce qui concerne les tests unitaires, examinez les modèles de conception du générateur. Il ajoute une interface et une classe supplémentaires pour chaque interface / classe actuelle que vous possédez, mais elles sont très petites et fournissent des fonctionnalités ÉNORMES pour un meilleur test unitaire.

cela aura un effet sur un object …. requête pour le résultat de l’effet. S’il n’y a pas d’effet visible, cela ne vaut pas les tests unitaires!

Vraisemblablement, la méthode fait quelque chose et ne revient pas simplement?

En supposant que ce soit le cas, alors:

  1. S’il modifie l’état de son object propriétaire, vous devez alors vérifier que l’état a changé correctement.
  2. S’il prend un object en tant que paramètre et modifie cet object, alors vous devriez tester que l’object est correctement modifié.
  3. Dans certains cas, si des exceptions sont émises, vérifiez que ces exceptions sont correctement générées.
  4. Si son comportement varie en fonction de l’état de son propre object ou de tout autre object, prédéfinissez l’état et testez la méthode à l’aide de l’une des trois méthodes de test ci-dessus.

Si vous nous faites savoir ce que la méthode fait, je pourrais être plus précis.

Utilisez Rhino Mocks pour définir les appels, les actions et les exceptions attendus. En supposant que vous pouvez simuler ou écarter certaines parties de votre méthode. Difficile à savoir sans connaître certaines spécificités de la méthode, voire du contexte.

Essaye ça:

 [TestMethod] public void TestSomething() { try { YourMethodCall(); Assert.IsTrue(true); } catch { Assert.IsTrue(false); } } 

Cela dépend de ce qu’il fait. Si elle contient des parameters, transmettez les moqueries que vous pourriez demander plus tard si elles ont été appelées avec le bon ensemble de parameters.

Quel que soit l’instance que vous utilisez pour appeler la méthode vide, vous pouvez simplement utiliser, Verfiy

Par exemple:

Dans mon cas, _Log est l’instance et LogMessage est la méthode à tester:

 try { this._log.Verify(x => x.LogMessage(Logger.WillisLogLevel.Info, Logger.WillisLogger.Usage, "Created the Student with name as"), "Failure"); } Catch { Assert.IsFalse(ex is Moq.MockException); } 

Est-ce que la Verify émet une exception en raison de l’échec de la méthode dont le test échoue?

Vous devez également vérifier si la méthode génère une exception.