web-dev-qa-db-fra.com

Modificateur d'accès "interne" en C # lors de tests unitaires

Je suis nouveau dans les tests unitaires et j'essaie de savoir si je devrais commencer à utiliser davantage de modificateur d'accès 'interne'. Je sais que si nous utilisons "interne" et définissons la variable Assembly "InternalsVisibleTo", nous pouvons tester des fonctions que nous ne voulons pas déclarer publiques à partir du projet de test. Cela me fait penser que je devrais juste toujours utiliser "interne" car au moins chaque projet (devrait?) A son propre projet de test. Pouvez-vous me dire une raison pour laquelle je ne devrais pas faire ça? Quand devrais-je utiliser "privé"?

396
Hertanto Lie

Les classes internes doivent être testées et il existe un attribut assembly:

using System.Runtime.CompilerServices;

[Assembly:InternalsVisibleTo("MyTests")]

Ajoutez ceci au fichier d’information sur le projet, par exemple. Properties\AssemblyInfo.cs.

1088
EricSchaefer

Si vous souhaitez tester des méthodes privées, consultez PrivateObject et PrivateType dans l'espace de noms Microsoft.VisualStudio.TestTools.UnitTesting. Ils offrent des wrappers faciles à utiliser autour du code de réflexion nécessaire.

Docs: PrivateType , PrivateObject

Pour VS2017 et 2019, vous pouvez les trouver en téléchargeant le nuget MSTest.TestFramework.

116
Brian Rasmussen

Vous pouvez également utiliser des méthodes privées et appeler des méthodes privées avec réflexion. Si vous utilisez Visual Studio Team Suite, il dispose de certaines fonctionnalités de Nice qui généreront un proxy pour appeler vos méthodes privées à votre place. Voici un article de projet de code qui montre comment vous pouvez effectuer vous-même le travail de test unitaire des méthodes privées et protégées:

http://www.codeproject.com/KB/cs/testnonpublicmembers.aspx

En ce qui concerne le modificateur d’accès que vous devez utiliser, ma règle générale est de commencer par privé et d’escalader au besoin. De cette façon, vous exposerez le moins possible de détails internes de votre classe, ce qui contribuera à masquer les détails de la mise en oeuvre, comme il se doit.

10
Steven Behnke

Continuez à utiliser privé par défaut. Si un membre ne doit pas être exposé au-delà de ce type, il ne doit pas l'être au-delà de ce type, même dans le même projet. Ceci garde les choses plus sûres et plus ordonnées - quand vous utilisez l'objet, vous voyez plus clairement les méthodes que vous êtes censé pouvoir utiliser.

Cela dit, je pense qu’il est raisonnable de faire parfois des méthodes naturellement privées à des fins de test. Je préfère cela à la réflexion, qui est un refactoring-hostile.

Une chose à considérer pourrait être un suffixe "ForTest":

internal void DoThisForTest(string name)
{
    DoThis(name);
}

private void DoThis(string name)
{
    // Real implementation
}

Ensuite, lorsque vous utilisez la classe dans le même projet, il est évident (maintenant et dans le futur) que vous ne devriez pas vraiment utiliser cette méthode. Elle est uniquement utilisée à des fins de test. C’est un peu hacky, et ce n’est pas quelque chose que je fais moi-même, mais cela mérite au moins d’être pris en considération.

10
Jon Skeet

En ajoutant à la réponse d'Eric, vous pouvez également configurer ceci dans le fichier csproj:

<ItemGroup>
    <AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleTo">
      <_Parameter1>MyTests</_Parameter1>
    </AssemblyAttribute>
</ItemGroup>

Ou si vous avez un projet de test à tester par projet, vous pouvez faire quelque chose comme ceci dans votre fichier Directory.Build.props:

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

Voir: https://stackoverflow.com/a/49978185/167805

7
gldraphael