24 Stimmen

Zugriff auf interne Mitglieder über System.Reflection?

Ich versuche, Unit Test eine Klasse, die viele interne Funktionen hat. Diese müssen natürlich auch getestet werden, aber meine Tests Projekt ist separat, vor allem, weil es viele kleine, verwandte Projekte umfasst. Was ich bis jetzt habe ist:

FieldInfo[] _fields = 
    typeof(ButtonedForm.TitleButton).GetFields(
        BindingFlags.NonPublic | BindingFlags.Instance | 
        BindingFlags.DeclaredOnly);
Console.WriteLine("{0} fields:", _fields.Length);
foreach (FieldInfo fi in _fields)
{
    Console.WriteLine(fi.Name);
}

Das spuckt zwar alle privaten Mitglieder aus, zeigt aber immer noch keine Interna an. Ich weiß, dass dies möglich ist, weil, wenn ich mit den automatisch generierten Tests, die Visual Studio produzieren kann, es fragte über etwas zu tun mit der Anzeige von Interna an das Test-Projekt durcheinander. Nun, jetzt bin ich mit NUnit und wirklich mag es, aber wie kann ich die gleiche Sache mit ihm erreichen?

32voto

Eric Schoonover Punkte 45504

Es wäre sinnvoller, den Begriff InternalsVisibleTo Attribut, um Ihrer Unit-Test-Assembly Zugriff auf die internen Mitglieder der Assembly zu gewähren.

Hier ist ein Link mit einigen hilfreichen zusätzlichen Informationen und einem Durchgang:

Um Ihre Frage tatsächlich zu beantworten... Intern und geschützt werden in der .NET Reflection API nicht erkannt. Hier ist ein Zitat aus MSDN :

Die C#-Schlüsselwörter protected und internal haben in AWL keine Bedeutung und werden in den Reflection-APIs nicht verwendet. Die entsprechenden Begriffe in IL sind Family und Assembly. Um eine interne Methode mit Reflection zu identifizieren, verwenden Sie die IsAssembly Eigenschaft. Um eine geschützte interne Methode zu identifizieren, verwenden Sie die IsFamilyOrAssembly .

6voto

Ash Punkte 58914

Hinzufügen der InternalsVisibleTo Attribut auf Baugruppenebene zu Ihrem Hauptprojekt mit dem Baugruppennamen des Testprojekts sollte die internen Mitglieder sichtbar machen.

Fügen Sie zum Beispiel folgendes in Ihre Assembly außerhalb einer Klasse ein:

[assembly: InternalsVisibleTo("AssemblyB")]

Oder für eine gezieltere Ausrichtung:

[assembly:InternalsVisibleTo("AssemblyB, PublicKey=32ab4ba45e0a69a1")]

Hinweis: Wenn Ihre Anwendungsbaugruppe einen starken Namen hat, muss auch Ihre Testbaugruppe einen starken Namen haben.

6voto

Mitch Wheat Punkte 287474

Ich denke, Sie müssen fragen, ob Sie Unit-Tests für private Methoden schreiben sollten? Wenn Sie Unit-Tests für Ihre öffentlichen Methoden schreiben, mit einer "vernünftigen" Codeabdeckung, testen Sie dann nicht bereits alle privaten Methoden, die als Ergebnis aufgerufen werden müssen?

Die Bindung von Tests an private Methoden macht die Tests brüchiger. Sie sollten in der Lage sein, die Implementierung privater Methoden zu ändern, ohne die Tests zu zerstören.

Verweise:

http://weblogs.asp.net/tgraham/archive/2003/12/31/46984.aspx http://richardsbraindump.blogspot.com/2008/08/should-i-unit-test-private-methods.html http://junit.sourceforge.net/doc/faq/faq.htm#tests_11 http://geekswithblogs.net/geekusconlivus/archive/2006/07/13/85088.aspx

6voto

Jon Skeet Punkte 1325502

Ihr Code zeigt nur Felder - so würde ich hoffen, dass es keine internen Mitglieder zeigen würde, da Felder immer privat IMO sein sollte. (Mit der möglichen Ausnahme von Konstanten.)

Hat ButtonedForm.TitleButton eigentlich irgendwelche nicht-privaten Felder? Wenn Sie versuchen, die internen Methoden dann müssen Sie natürlich die GetMethods (ou GetMembers ), um an sie heranzukommen.

Wie andere vorgeschlagen haben, InternalsVisibleTo ist sehr praktisch zum Testen (und fast ausschließlich zum Testen!). Was die Frage betrifft, ob Sie interne Methoden testen sollten - ich finde es auf jeden Fall nützlich, dies tun zu können. Ich betrachte Unit-Tests nicht als ausschließlich Blackbox-Tests. Wenn Sie wissen, dass die öffentliche Funktionalität mit Hilfe einiger interner Methoden implementiert wird, die auf einfache Weise miteinander verbunden sind, ist es oft einfacher, gründliche Tests für jede der internen Methoden und einige "Pseudo-Integrationstests" für die öffentliche Methode durchzuführen.

1voto

Eine Rechtfertigung für die Verwendung von InternalsVisible ist unter meinen Umständen. Wir kaufen den Quellcode eines Chart Controls. Wir haben festgestellt, dass wir einige Änderungen an diesem Quellcode vornehmen und unsere eigene Version kompilieren müssen. Um sicherzustellen, dass wir nichts kaputt gemacht haben, muss ich nun einige Unit-Tests schreiben, die Zugriff auf einige interne Felder benötigen.

Dies ist ein perfekter Fall, in dem InternalsVisible sinnvoll ist.

Ich frage mich jedoch, was Sie tun können, wenn Sie keinen Zugriff auf die Quelle haben? Wie könnte man an ein internes Feld gelangen? .Net Reflector kann diesen Code sehen, aber ich schätze, er schaut sich nur die IL an.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X