Visual Studio permet le test unitaire des méthodes privées via une classe d'accesseur générée automatiquement. J'ai écrit un test d'une méthode privée qui se compile avec succès, mais elle échoue au moment de l'exécution. Une version assez minimale du code et du test est:
//in project MyProj
class TypeA
{
private List<TypeB> myList = new List<TypeB>();
private class TypeB
{
public TypeB()
{
}
}
public TypeA()
{
}
private void MyFunc()
{
//processing of myList that changes state of instance
}
}
//in project TestMyProj
public void MyFuncTest()
{
TypeA_Accessor target = new TypeA_Accessor();
//following line is the one that throws exception
target.myList.Add(new TypeA_Accessor.TypeB());
target.MyFunc();
//check changed state of target
}
L'erreur d'exécution est:
Object of type System.Collections.Generic.List`1[MyProj.TypeA.TypeA_Accessor+TypeB]' cannot be converted to type 'System.Collections.Generic.List`1[MyProj.TypeA.TypeA+TypeB]'.
Selon intellisense - et donc je suppose que le compilateur - la cible est de type TypeA_Accessor. Mais au moment de l'exécution, il est de type TypeA, et donc l'ajout de liste échoue.
Est-il possible d'arrêter cette erreur? Ou, peut-être plus probablement, quels autres conseils ont d'autres personnes (je prédis peut-être "ne testez pas les méthodes privées" et "ne faites pas de tests unitaires manipuler l'état des objets").
c#
unit-testing
junichiro
la source
la source
Réponses:
Oui, ne testez pas les méthodes privées .... L'idée d'un test unitaire est de tester l'unité par son 'API' publique.
Si vous constatez que vous devez tester un grand nombre de comportements privés, il est fort probable que vous ayez une nouvelle `` classe '' cachée dans la classe que vous essayez de tester, extrayez-la et testez-la par son interface publique.
Un conseil / outil de réflexion ... Il y a une idée qu'aucune méthode ne devrait jamais être privée. Cela signifie que toutes les méthodes doivent vivre sur une interface publique d'un objet .... si vous sentez que vous devez le rendre privé, il vit très probablement sur un autre objet.
Ce conseil ne fonctionne pas tout à fait dans la pratique, mais c'est surtout un bon conseil, et souvent il poussera les gens à décomposer leurs objets en objets plus petits.
la source
Vous pouvez utiliser la classe PrivateObject
la source
"Il n'y a rien qui soit appelé standard ou meilleure pratique, ce ne sont probablement que des opinions populaires".
Il en va de même pour cette discussion également.
Tout dépend de ce que vous pensez être une unité, si vous pensez que UNIT est une classe, vous ne frapperez que la méthode publique. Si vous pensez que UNIT est une ligne de code qui utilise des méthodes privées, vous ne vous sentirez pas coupable.
Si vous souhaitez appeler des méthodes privées, vous pouvez utiliser la classe "PrivateObject" et appeler la méthode invoke. Vous pouvez regarder cette vidéo youtube approfondie ( http://www.youtube.com/watch?v=Vq6Gcs9LrPQ ) qui montre comment utiliser "PrivateObject" et explique également si les tests des méthodes privées sont logiques ou non.
la source
Une autre pensée ici est d'étendre les tests aux classes / méthodes "internes", en donnant plus de sens en boîte blanche de ces tests. Vous pouvez utiliser InternalsVisibleToAttribute sur l'assembly pour les exposer à des modules de test unitaires distincts.
En combinaison avec une classe scellée, vous pouvez approcher une telle encapsulation que la méthode de test n'est visible que depuis l'assemblage le plus uniforme de vos méthodes. Considérez que la méthode protégée en classe scellée est de facto privée.
Et test unitaire:
la source
Une façon de tester des méthodes privées est la réflexion. Cela s'applique également à NUnit et XUnit:
la source
call methods
statique et non statique ?Ermh ... Entré ici avec exactement le même problème: Testez une méthode privée simple , mais pivot . Après avoir lu ce fil, il semble que "Je veux percer ce simple trou dans ce simple morceau de métal, et je veux m'assurer que la qualité correspond aux spécifications", puis vient "D'accord, ce n'est pas facile. Tout d'abord, il n'y a pas d'outil approprié pour le faire, mais vous pouvez construire un observatoire des ondes gravitationnelles dans votre jardin. Lisez mon article sur http://foobar.brigther-than-einstein.org/ Tout d'abord, bien sûr, vous devez suivre des cours avancés de physique quantique, alors vous avez besoin de tonnes d'azote ultra-cool, puis, bien sûr, mon livre disponible sur Amazon "...
En d'autres termes...
Non, tout d'abord.
Chaque méthode, qu'elle soit privée, interne, protégée, publique doit être testable. Il doit y avoir un moyen de mettre en œuvre de tels tests sans autant d'agitation comme cela a été présenté ici.
Pourquoi? Exactement à cause des mentions architecturales faites jusqu'à présent par certains contributeurs. Peut-être qu'une simple réitération des principes du logiciel pourrait dissiper certains malentendus.
Dans ce cas, les suspects habituels sont: OCP, SRP et, comme toujours, KIS.
Mais attendez une minute. L'idée de rendre tout accessible au public est plus ou moins politique et une sorte d'attitude. Mais. En ce qui concerne le code, même dans la communauté Open Source, ce n'est pas un dogme. Au lieu de cela, «cacher» quelque chose est une bonne pratique pour faciliter la familiarisation avec une certaine API. Vous cacheriez, par exemple, les calculs de base de votre bloc de construction de thermomètre numérique nouveau sur le marché - non pas pour cacher les mathématiques derrière la vraie courbe mesurée aux lecteurs de code curieux, mais pour empêcher votre code de devenir dépendant de certains, peut-être soudainement des utilisateurs importants qui n'ont pas pu résister à utiliser votre ancien code privé, interne et protégé pour implémenter leurs propres idées.
De quoi je parle?
Il est facile de proclamer l'ère du Verseau ou ce qu'on appelle aujourd'hui, mais si mon morceau de capteur passe de 1.0 à 2.0, la mise en œuvre de Translate ... pourrait changer d'une simple équation linéaire facilement compréhensible et utilisable "pour tout le monde, à un calcul assez sophistiqué qui utilise l'analyse ou autre chose, et donc je casserais le code des autres. Pourquoi? Parce qu'ils ne comprenaient pas les principes mêmes du codage logiciel, pas même KIS.
Pour faire court ce conte de fées: Nous avons besoin d'un moyen simple de tester des méthodes privées - sans tarder.
Premièrement: bonne année à tous!
Deuxièmement: répétez vos leçons d'architecte.
Troisièmement: le modificateur «public» est la religion, pas une solution.
la source
Une autre option qui n'a pas été mentionnée consiste simplement à créer la classe de test unitaire en tant qu'enfant de l'objet que vous testez. Exemple NUnit:
Cela permettrait de tester facilement des méthodes privées et protégées (mais pas héritées privées), et cela vous permettrait de garder tous vos tests séparés du code réel afin de ne pas déployer des assemblys de test en production. Passer de vos méthodes privées à des méthodes protégées serait acceptable dans de nombreux objets hérités, et c'est une modification assez simple à effectuer.
TOUTEFOIS...
Bien qu'il s'agisse d'une approche intéressante pour résoudre le problème de la façon de tester des méthodes cachées, je ne suis pas sûr de recommander que ce soit la bonne solution au problème dans tous les cas. Il semble un peu étrange de tester en interne un objet, et je soupçonne qu'il pourrait y avoir des scénarios où cette approche vous exploserait. (Les objets immuables, par exemple, peuvent rendre certains tests très difficiles).
Bien que je mentionne cette approche, je dirais qu'il s'agit davantage d'une suggestion de remue-méninges que d'une solution légitime. Prenez-le avec un grain de sel.
EDIT: Je trouve vraiment hilarant que les gens votent contre cette réponse, car je décris explicitement cela comme une mauvaise idée. Est-ce à dire que les gens sont d'accord avec moi? Je suis tellement confus.....
la source
Extrait du livre Working Effectively with Legacy Code :
Selon l'auteur, la solution consiste à créer une nouvelle classe et à ajouter la méthode as
public
.L'auteur explique plus loin:
Donc, dans ces limites, votre seule vraie option est de faire la méthode
public
, soit dans la classe actuelle soit dans une nouvelle classe.la source
TL; DR: Extraire la méthode privée dans une autre classe, tester sur cette classe; en savoir plus sur le principe SRP (principe de responsabilité unique)
Il semble que vous ayez besoin d'extraire la
private
méthode vers une autre classe; dans ce devrait êtrepublic
. Au lieu d'essayer de tester laprivate
méthode, vous devez tester lapublic
méthode de cette autre classe.Nous avons le scénario suivant:
Nous devons tester la logique de
_someLogic
; mais il semble que celaClass A
prenne plus de rôle qu'il n'en a besoin (violer le principe SRP); juste refactoriser en deux classesDe cette façon,
someLogic
pourrait être testé sur A2; dans A1, il suffit de créer un faux A2 puis d'injecter au constructeur pour tester que A2 est appelé dans la fonction nomméesomeLogic
.la source
Dans VS 2005/2008, vous pouvez utiliser un accesseur privé pour tester un membre privé, mais cette méthode a disparu dans la version ultérieure de VS
la source