Wie erlaube ich einer Baugruppe (Unit Testing One), auf interne Eigenschaften einer anderen Baugruppe zuzugreifen?

80

Ich möchte, dass meine Core-Assembly eine bestimmte Klasse nicht verfügbar macht, und ich möchte sie trotzdem testen können. Wie kann ich das machen ?

Tomas Pajonk
quelle

Antworten:

107

InternalsVisibleTo Attribut zur Rettung!

Einfach hinzufügen:

[assembly:InternalsVisibleToAttribute("UnitTestAssemblyName")]

zu Ihrer AssemblyInfo.cs-Datei der Kernklassen

Best Practices finden Sie unter Friend Assemblies (C # -Programmierhandbuch) .

aku
quelle
3
Ich habe dies gerade erfolgreich mit einer stark benannten Versammlung durchgeführt, die den Anweisungen folgt, auf die aku verweist. Ich hatte allerdings ein Problem. Nachdem ich alles konfiguriert hatte, musste ich Visual Studio neu starten, damit Intellisense funktioniert. Es würde vor dem Neustart kompiliert, aber immer die roten Linien anzeigen.
Eric Schoonover
20

Wenn Ihre Assemblys bei InternalsVisible einen starken Namen haben, müssen Sie beispielsweise den öffentlichen Schlüssel angeben (Hinweis: der vollständige Schlüssel, nicht das Token für den öffentlichen Schlüssel) ...

[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("BoardEx_BusinessObjects.Tests, 
  PublicKey=0024000004800000940000000602000000240000525341310004000001000100fb3a2d8 etc etc")]

und der folgende Trick ist wirklich nützlich, um den öffentlichen Schlüssel zu erhalten, ohne auf die cmd-Zeile zurückzugreifen ...

http://www.andrewconnell.com/blog/archive/2006/09/15/4587.aspx

Simon Keep
quelle
9

Ich habe meine Komponententests in dieselbe Assembly gestellt wie den Code, den sie testen. Das macht für mich Sinn, weil ich "Test dich selbst" als Merkmal einer Klasse betrachte, zusammen mit Dingen wie "Initialisiere dich selbst" und "Beschreibe dich selbst".

Ich habe einige Einwände gegen diesen Ansatz gehört, aber nur wenige davon haben überzeugt.

Es tut weh, Bah, sage ich! Nicht ohne harte Daten optimieren! Wenn Sie planen, dass Ihre Assemblys über langsame Links heruntergeladen werden, lohnt es sich möglicherweise, die Assemblygröße zu minimieren.

Es ist ein Sicherheitsrisiko . Nur wenn Sie Geheimnisse in Ihren Tests haben. Tu das nicht.

Jetzt ist Ihre Situation anders als meine. Vielleicht macht es für Sie Sinn und vielleicht auch nicht. Das müssen Sie selbst herausfinden.

Nebenbei: In C # habe ich einmal versucht, meine Komponententests in eine Klasse mit dem Namen "Tests" einzufügen, die in der zu testenden Klasse verschachtelt war. Dies machte die richtige Organisation der Dinge offensichtlich. Es wurde auch das Duplizieren von Namen vermieden, das auftritt, wenn Tests für die Klasse "Foo" in einer Klasse namens "FooTests" durchgeführt werden. Die Unit-Test-Frameworks, auf die ich Zugriff hatte, lehnten es jedoch ab, Tests zu akzeptieren, die nicht als "öffentlich" gekennzeichnet waren. Dies bedeutet, dass die Klasse, die Sie testen, nicht "privat" sein kann. Ich kann mir keinen guten Grund vorstellen, zu verlangen, dass Tests "öffentlich" sind, da niemand sie wirklich als öffentliche Methoden bezeichnet - alles geschieht durch Reflexion. Wenn Sie jemals ein Unit-Test-Framework für .Net schreiben, ziehen Sie bitte in Betracht, nicht öffentliche Tests zuzulassen, um meinetwillen!

Jay Bazuzi
quelle
5
Interessanter Ansatz. Und ich stimme voll und ganz zu, dass Tests öffentlich sind. Dumme Anforderung, IMO.
Kilhoffer
@Kilhoffer: Ich habe mich jahrelang darüber beschwert und du bist der erste, der mir wirklich zustimmt. Vielen Dank!
Jay Bazuzi
6
Wenn Sie [Conditional("DEBUG")]Testklassen verwenden, sollten diese nicht in der Produktionsbaugruppe enthalten sein und die Leistung nicht beeinträchtigen.
Xmedeko
3

Ich würde vorschlagen, sich nicht mit solchen Problemen zu befassen. Wenn Sie Ihre "internen" Klassen wirklich einem Unit-Test unterziehen möchten, verstecken Sie sie einfach in einem Namespace, den nur Ihr interner Code verwenden würde. Wenn Sie kein Framework im Maßstab des .NET-Frameworks schreiben, benötigen Sie diese Ebene des Versteckens nicht wirklich .

Joel Martinez
quelle
Ich wollte genau das kommentieren, was Sie gesagt haben, als ich Ihren Kommentar unten bemerkte. +1! :)
Björn Reppen
2

Sie können Reflection verwenden (wie dies bei den MS-Testelementen der Fall ist) oder die Unit-Test-Assembly als Freund der Core-Assembly deklarieren.

Die andere Möglichkeit besteht darin, die Komponententests in derselben Baugruppe zu platzieren.

Dan Blair
quelle