J'ai constaté qu'il n'y a que 3 façons de dépendre d'un test unitaire (fictif / stub) statique dans C # .NET:
Étant donné que deux d’entre eux ne sont pas gratuits et que l’un n’a pas encore atteint la version 1.0, se moquer de choses statiques n’est pas si facile.
Est-ce que cela rend les méthodes statiques et un tel "mal" (dans le sens de tests unitaires)? Et si oui, pourquoi le resharper veut-il que je fasse tout ce qui peut être statique, statique? (En supposant que resharper n'est pas aussi "mauvais".)
Précision: Je parle du scénario quand vous voulez tester l' unité une méthode et cette méthode appelle une méthode statique dans une autre unité / classe. Selon la plupart des définitions de test unitaire, si vous laissez simplement la méthode testée appeler la méthode statique dans l’autre unité / classe, vous ne testez pas l’ unité, mais bien le test d’ intégration . (Utile, mais pas un test unitaire.)
la source
Réponses:
En regardant les autres réponses ici, je pense qu'il pourrait y avoir une certaine confusion entre les méthodes statiques qui maintiennent un état statique ou provoquent des effets secondaires (ce qui me semble une très mauvaise idée) et les méthodes statiques qui renvoient simplement une valeur.
Les méthodes statiques qui ne tiennent aucun état et ne provoquent aucun effet secondaire devraient être facilement testables à l'unité. En fait, je considère de telles méthodes comme une forme de programmation fonctionnelle du "pauvre homme"; vous remettez à la méthode un objet ou une valeur, qui renvoie un objet ou une valeur. Rien de plus. Je ne vois pas en quoi de telles méthodes auraient un impact négatif sur les tests unitaires.
la source
Vous semblez confondre les données statiques et les méthodes statiques . Si je me souviens bien, Resharper recommande de rendre les
private
méthodes d'une classe statiques si elles peuvent l'être - je pense que cela produit un petit avantage en termes de performances. Il ne recommande pas de faire "tout ce qui peut être" statique!Il n’ya rien de mal avec les méthodes statiques et elles sont faciles à tester (tant qu’elles ne modifient pas les données statiques). Par exemple, pensez à une bibliothèque Maths, qui est un bon candidat pour une classe statique avec des méthodes statiques. Si vous avez une méthode (artificielle) comme celle-ci:
alors cela est éminemment testable et n’a pas d’effets secondaires. Vous vérifiez que lorsque vous passez, par exemple, vous en récupérez 400. Pas de problème.
la source
System.Math
utilisent des méthodes statiques dans d'autres classes (telles que ), sans parler de l'abondance des méthodes d'usine statique, etc. De plus, vous ne pourrez jamais utiliser de méthodes d'extension, etc. fondamental aux langues modernes. Vous pouvez les tester isolément (car ils seront généralement déterministes), puis les utiliser dans vos classes sans souci. Ce n'est pas un problème!Si la vraie question est "Comment puis-je tester ce code?":
Ensuite, il suffit de refactoriser le code et d’injecter comme d’habitude l’appel à la classe statique comme ceci:
la source
Les statiques ne sont pas nécessairement diaboliques, mais elles peuvent limiter vos options en matière de tests unitaires avec des faux / mocs / moignons.
Il existe deux approches générales pour se moquer.
Le premier (traditionnel - mis en œuvre par RhinoMocks, Moq, NMock2; des simulacres et des bouts manuels se trouvent également dans ce camp) repose sur des coutures de test et une injection de dépendance. Supposons que vous testiez du code statique avec des dépendances. Ce qui se produit souvent dans le code conçu de cette manière, c’est que les statiques créent leurs propres dépendances, en inversant l’ inversion des dépendances . Vous découvrez bientôt que vous ne pouvez pas injecter d'interfaces simulées dans un code à tester conçu de cette manière.
La seconde (rien à faire - implémentée par TypeMock, JustMock et Moles) repose sur l’ API de profilage de .NET . Il peut intercepter n'importe laquelle de vos instructions CIL et remplacer une partie de votre code par un faux. Cela permet à TypeMock et aux autres produits de ce camp de se moquer de n'importe quoi: statique, classes scellées, méthodes privées - des éléments non conçus pour être testés.
Il y a un débat en cours entre deux écoles de pensée. On dit, suivez les principes et la conception de SOLID pour la testabilité (cela implique souvent de passer facilement à la statique). L'autre dit, achetez TypeMock et ne vous inquiétez pas.
la source
Cochez cette case: "Les méthodes statiques sont mortelles pour la testabilité" . Bref résumé de l'argumentation:
Pour tester les unités, vous devez prendre un petit morceau de votre code, recâbler ses dépendances et le tester isolément. Cela est difficile avec les méthodes statiques, non seulement dans le cas où elles accèdent à l'état global, mais même si elles n'appellent que d'autres méthodes statiques.
la source
La simple vérité rarement reconnue est que si une classe contient une dépendance visible du compilateur sur une autre classe, elle ne peut pas être testée indépendamment de cette classe. Vous pouvez simuler quelque chose qui ressemble à un test et qui apparaîtra dans un rapport comme s'il s'agissait d'un test.
Mais il n'aura pas les propriétés clés définissant un test; échouer quand les choses vont mal, passer quand ils ont raison.
Ceci s'applique à tous les appels statiques, aux appels de constructeur et à toute référence à des méthodes ou à des champs non hérités d'une classe ou d'une interface de base . Si le nom de la classe apparaît dans le code, il s'agit d'une dépendance visible du compilateur, et vous ne pouvez pas valider sans elle. Tout petit morceau n'est tout simplement pas une unité testable valide . Toute tentative visant à le traiter comme tel ne produira pas de résultats plus significatifs que l'écriture d'un petit utilitaire permettant d'émettre le code XML utilisé par votre infrastructure de test pour indiquer 'test réussi'
Compte tenu de cela, il existe trois options:
définissez les tests unitaires comme des tests de l'unité composée d'une classe et de ses dépendances codées en dur. Cela fonctionne, à condition d'éviter les dépendances circulaires.
ne créez jamais de dépendances à la compilation entre les classes que vous êtes chargé de tester. Cela fonctionne, à condition que le style de code obtenu ne vous dérange pas.
ne faites pas de test unitaire, mais un test d'intégration. Ce qui fonctionne, à condition que cela n'entre pas en conflit avec quelque chose d'autre pour lequel vous devez utiliser le terme tests d'intégration.
la source
Math.Pi
dans une méthode n'en fait pas un test d'intégration selon une définition raisonnable.Il n'y a pas deux manières à ce sujet. Les suggestions de ReSharper et plusieurs fonctionnalités utiles de C # ne seraient pas utilisées aussi souvent si vous écriviez des tests d'unité atomique isolés pour tout votre code.
Par exemple, si vous avez une méthode statique et que vous devez l'exclure, vous ne pouvez pas le faire sauf si vous utilisez un cadre d'isolation basé sur un profil. Une solution de contournement compatible avec les appels consiste à modifier le haut de la méthode pour utiliser la notation lambda. Par exemple:
AVANT:
APRÈS:
Les deux sont compatibles avec les appels. Les appelants n'ont pas à changer. Le corps de la fonction reste le même.
Ensuite, dans votre code de test unitaire, vous pouvez stub cet appel comme suit (en supposant qu'il soit dans une classe appelée Database):
Veillez à le remplacer par la valeur d'origine une fois que vous avez terminé. Vous pouvez le faire via try / finally ou, lors du nettoyage d'un test un, celui qui est appelé après chaque test, écrivez un code tel que celui-ci:
qui ré-invoquera l'initialiseur statique de votre classe.
Les fonctions lambda ne sont pas aussi riches en support que les méthodes statiques classiques, cette approche a donc les effets secondaires indésirables suivants:
Mais supposons que vous évitiez complètement la statique et que vous convertissiez cela en une méthode d'instance. Ce n'est toujours pas mockable sauf si la méthode est virtuelle ou implémentée dans le cadre d'une interface.
Donc, en réalité, quiconque suggère que le remède aux méthodes statiques réductrices consiste à en faire des méthodes d'instance, ils seraient également opposés aux méthodes d'instance qui ne sont pas virtuelles ou ne font pas partie d'une interface.
Alors pourquoi C # a-t-il des méthodes statiques? Pourquoi autorise-t-il les méthodes d'instance non virtuelle?
Si vous utilisez l'une de ces "fonctionnalités", vous ne pouvez tout simplement pas créer de méthodes isolées.
Alors quand les utilisez-vous?
Utilisez-les pour tout code dont vous ne vous attendez pas à ce que quelqu'un veuille se démarquer. Quelques exemples: la méthode Format () de la classe String la méthode WriteLine () de la classe Console la méthode Cosh () de la classe Math
Et encore une chose ... La plupart des gens ne s’en soucieront pas, mais si vous le pouvez sur la performance d’un appel indirect, c’est une autre raison pour éviter les méthodes d’instance. Il y a des cas où c'est un coup dur pour la performance. C'est pourquoi les méthodes non virtuelles existent en premier lieu.
la source
R # n'est pas le seul outil qui fera cette suggestion. L'analyse de code FxCop / MS fera également de même.
Je dirais généralement que si la méthode est statique, elle devrait généralement pouvoir être testée telle quelle. Cela amène quelques considérations de conception et probablement plus de discussion que je n’en ai entre les doigts pour le moment, alors attendez patiemment les votes négatifs et les commentaires ...;)
la source
Je vois qu'après longtemps personne n'a encore énoncé un fait très simple. Si le revendeur me dit que je peux rendre une méthode statique, cela signifie une chose énorme pour moi, je peux entendre sa voix me dire: "Hé, toi, ces éléments de la logique ne sont pas de la responsabilité de la classe actuelle à gérer, donc ils doivent rester en dehors dans une classe d'assistance ou quelque chose ".
la source
Si la méthode statique est appelée depuis une autre méthode , il est impossible d'empêcher ou de substituer un tel appel. Cela signifie que ces deux méthodes forment une seule unité. Les tests unitaires de tous types les testent tous les deux.
Et si cette méthode statique communique avec Internet, connecte des bases de données, affiche des fenêtres contextuelles d'interface graphique ou convertit le test d'unité en désordre total, elle ne nécessite aucun travail simple. Une méthode qui appelle une telle méthode statique n'est pas testable sans refactoring, même si elle contient beaucoup de code purement informatique qui bénéficierait grandement d'un test unitaire.
la source
Je pense que Resharper vous donne la confiance et applique les directives de codage avec lesquelles il a été configuré. Lorsque j'ai utilisé Resharper et qu'il m'a indiqué qu'une méthode devrait être statique, elle doit nécessairement être sur une méthode privée qui n'agit sur aucune variable d'instance.
Maintenant, en ce qui concerne la testabilité, ce scénario ne devrait pas être un problème car vous ne devriez de toute façon pas tester les méthodes privées.
En ce qui concerne la testabilité des méthodes statiques publiques, les tests unitaires deviennent difficiles lorsque les méthodes statiques entrent en contact avec un état statique. Personnellement, je le limiterais au minimum et utiliserais autant que possible des méthodes statiques sous forme de fonctions pures, dans lesquelles toutes les dépendances seraient transmises à la méthode et contrôlables via un appareil de test. Cependant, ceci est une décision de conception.
la source