it-swarm.com.de

C # "interner" Zugriffsmodifikator beim Testen von Einheiten

Ich bin neu in Unit-Tests und ich versuche herauszufinden, ob ich anfangen sollte, mehr "interne" Zugriffsmodifikatoren zu verwenden. Ich weiß, dass wir, wenn wir 'internal' verwenden und die Assembly-Variable 'InternalsVisibleTo' setzen, Funktionen testen können, die wir aus dem Testprojekt nicht als öffentlich deklarieren möchten. Das lässt mich denken, dass ich einfach immer 'intern' verwenden sollte, da zumindest jedes Projekt (sollte?) Ein eigenes Testprojekt hat. Kannst du mir einen Grund nennen, warum ich das nicht tun sollte? Wann sollte ich "privat" verwenden?

396
Hertanto Lie

Interne Klassen müssen getestet werden und es gibt ein Assembly-Attribut:

using System.Runtime.CompilerServices;

[Assembly:InternalsVisibleTo("MyTests")]

Fügen Sie dies der Projektinfodatei hinzu, z. Properties\AssemblyInfo.cs.

1088
EricSchaefer

Wenn Sie private Methoden testen möchten, schauen Sie sich PrivateObject und PrivateType in der Microsoft.VisualStudio.TestTools.UnitTesting Namespace. Sie bieten benutzerfreundliche Wrapper für den erforderlichen Reflektionscode.

Dokumente: PrivateType , PrivateObject

Für VS2017 und 2019 können Sie diese finden, indem Sie das Nuget MSTest.TestFramework herunterladen

116
Brian Rasmussen

Sie können auch private verwenden und private Methoden mit Reflektion aufrufen. Wenn Sie Visual Studio Team Suite verwenden, verfügt es über einige nette Funktionen, die einen Proxy generieren, um Ihre privaten Methoden für Sie aufzurufen. Hier ist ein Artikel aus einem Code-Projekt, der zeigt, wie Sie die Arbeit selbst erledigen können, um private und geschützte Methoden in einem Komponententest zu testen:

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

In Bezug auf den Zugriffsmodifikator, den Sie verwenden sollten, ist meine allgemeine Faustregel, mit privat zu beginnen und nach Bedarf zu eskalieren. Auf diese Weise legen Sie so wenig interne Details Ihrer Klasse offen, wie wirklich benötigt werden, und es hilft dabei, die Implementierungsdetails so zu verbergen, wie sie sollten.

10
Steven Behnke

Standardmäßig weiterhin privat verwenden. Wenn ein Member nicht über diesen Typ hinaus verfügbar gemacht werden soll, sollte es auch innerhalb desselben Projekts nicht über diesen Typ hinaus verfügbar gemacht werden. Dies sorgt für mehr Sicherheit und Ordnung - wenn Sie das Objekt verwenden, wird klarer, welche Methoden Sie verwenden sollen.

Trotzdem halte ich es manchmal für vernünftig, natürlich-private Methoden für Testzwecke intern zu machen. Ich bevorzuge die Verwendung von Reflection, die unfreundlich für Refactoring ist.

Eine zu berücksichtigende Sache könnte ein "ForTest" -Suffix sein:

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

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

Wenn Sie die Klasse innerhalb desselben Projekts verwenden, ist es (jetzt und in Zukunft) offensichtlich, dass Sie diese Methode nicht wirklich verwenden sollten - sie dient nur zu Testzwecken. Das ist ein bisschen abgedreht und nichts, was ich selbst mache, aber es ist zumindest eine Überlegung wert.

10
Jon Skeet

Als Ergänzung zu Erics Antwort können Sie dies auch in der Datei csproj konfigurieren:

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

Oder wenn Sie ein Testprojekt pro zu testendem Projekt haben, können Sie in Ihrem Directory.Build.props Datei:

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

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

7
gldraphael