Test unitaire des méthodes internes dans la bibliothèque VS2017 .Net Standard

150

Je joue actuellement avec la dernière version de Visual Studio 2017 Release Candidate en créant une bibliothèque .Net Standard 1.6. J'utilise xUnit pour tester mon code unitaire et je me demande si vous pouvez toujours tester des méthodes internes dans VS2017.

Je me souviens que vous pourriez toute une classe AssemblyInfo.cs en ligne dans VS2015 qui permettrait aux projets spécifiés de voir les méthodes internes

[assembly:InternalsVisibleTo("MyTests")]

Comme il n'y a pas de classe AssemblyInfo.cs dans les projets VS2017 .Net Standard, je me demandais si vous pouviez encore tester des méthodes internes?

Phil Murray
la source
3
Vous devriez être en mesure de tester votre code à partir de fonctionnalités visibles de l'extérieur uniquement. Après tout, si aucun chemin logique à partir du code externe ne peut atteindre ces méthodes internes, que feraient-ils là en premier lieu?
David
3
@David Je peux et je l'ai fait, mais j'ai déjà mis des tests unitaires simples autour de certaines classes internes. Juste pour être plus explicite dans les tests.
Phil Murray
5
AFAIK, vous pouvez placer cet attribut dans n'importe quel autre fichier, en dehors du namespacebloc, et il devrait compiler. Il ne devrait rien y avoir de magique AssemblyInfo.cs. Ça marche pas? Bien sûr, vous devez ajouter la usingclause correcte ou utiliser l'attribut pleinement qualifié [assembly: System.Runtime.CompilerServices.InternalsVisibleTo("Something")].
Groo
1
@David Si vous créez une bibliothèque avec des classes internes et que vous avez besoin de tester et de simuler ces classes, il InternalsVisibleToest essentiel - par exemple ici - stackoverflow.com/a/17574183/43453
PandaWood

Réponses:

210

Selon la documentation .NET pourInternalsVisibleToAttribute :

L'attribut est appliqué au niveau de l'assemblage. Cela signifie qu'il peut être inclus au début d'un fichier de code source ou qu'il peut être inclus dans le fichier AssemblyInfo dans un projet Visual Studio.

En d'autres termes, vous pouvez simplement le placer dans votre propre fichier .cs nommé arbitrairement, et cela devrait fonctionner correctement:

// some .cs file included in your project
using System.Runtime.CompilerServices;
[assembly:InternalsVisibleTo("MyTests")]
Groo
la source
1
@PhilMurray: aussi, il semble qu'il y ait un paramètre qui devrait vous permettre de créer un AssemblyInfo.csfichier "classique" comme expliqué ici . Sinon, tous les attributs comme "description", "copyright" et autres sont stockés dans le fichier .csproj.
Groo
43

Comme décrit ici:

https://blog.sanderaernouts.com/make-internals-visible-with-new-csproj-format

Il est possible d'ajouter l'attribut visible interne dans le fichier projet en ajoutant un autre ItemGroup:

<ItemGroup>
    <AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleTo">
        <_Parameter1>$(AssemblyName).Tests</_Parameter1>
    </AssemblyAttribute>
</ItemGroup>

ou même:

<ItemGroup>
    <AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleTo">
        <_Parameter1>$(MSBuildProjectName).Tests</_Parameter1>
    </AssemblyAttribute>
</ItemGroup>

J'aime cette solution car le dossier de projet semble être le bon endroit pour définir de telles préoccupations.

JanDotNet
la source
8

Alors que la première réponse est parfaitement bien. Si vous pensez que vous souhaitez toujours le faire dans l'original, AssemblyInfovous pouvez toujours choisir de ne pas générer automatiquement le fichier et de l'ajouter manuellement.

<PropertyGroup>
   <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
</PropertyGroup>

Pour plus d'informations: https://stackoverflow.com/a/47075759/869033

Nick N.
la source
5

L'attribut "InternalsVisibleTo" est la clé de toute sorte de "boîte blanche" (le terme de la décennie, je suppose) pour tester .Net. Il peut être placé dans n'importe quel fichier c # avec l'attribut "assembly" au recto. Notez que MS DOCs indiquent que le nom d'assembly doit être qualifié par le jeton de clé publique, s'il est signé. Parfois, cela ne fonctionne pas et il faut utiliser la clé publique complète à sa place. L'accès aux composants internes est essentiel pour tester des systèmes concurrents et dans de nombreuses autres situations. Voir https://www.amazon.com/xUnit-Test-Patterns-Refactoring-Code/dp/0131495054 . Dans ce livre, Meszaros décrit une variété de styles de codage qui constituent essentiellement une approche «Design For Test» pour le développement de programmes. Du moins, c'est ainsi que je l'ai utilisé au fil des ans.

AJOUTÉ: Désolé, je n'ai pas été ici depuis un moment. Une approche est appelée l'approche "sous-classe de test" par Meszaros. Encore une fois, il faut utiliser "internalsvisableto" pour accéder aux internes de la classe de base. C'est une excellente solution, mais cela ne fonctionne pas pour les classes scellées. Quand j'enseigne "Design For Test", je suggère que c'est l'une des choses qui doivent être "pré-conçues" dans les classes de base afin de fournir la testabilité. Cela doit devenir presque une chose culturelle. Concevez une classe de base "de base" non scellée. Appelez-le UnsealedBaseClass ou quelque chose de uniformément reconnaissable. Il s'agit de la classe à sous-classer pour les tests. Il est également sous-classé pour créer la classe scellée de production, qui ne diffère souvent que par les constructeurs qu'elle expose. Je travaille dans l'industrie nucléaire et les exigences d'essais sont prises TRÈS au sérieux. Donc, je dois penser à ces choses tout le temps. Par ailleurs, laisser les hooks de test dans le code de production n'est pas considéré comme un problème dans notre domaine, tant qu'ils sont "internes" dans une implémentation .Net. Les ramifications de NE PAS tester quelque chose peuvent être assez profondes.

kurt.matis
la source
1

Une autre façon est d'utiliser une classe publique TestMyFoo «wrapper» à l'intérieur du projet cible qui a des méthodes publiques et hérite de la classe que vous devez tester (par exemple MyFoo). Ces méthodes publiques font simplement appel à la classe de base que vous souhaitez tester.

Ce n'est pas «idéal» car vous finissez par envoyer un crochet de test dans votre projet cible. Mais considérez que les voitures modernes et fiables sont livrées avec des ports de diagnostic et les navires électroniques modernes et fiables avec une connexion JTAG. Mais personne n'est assez stupide pour conduire sa voiture en utilisant le port de diagnostic.

andrew pate
la source