16

[Natürlich ist die Frage nicht auf eine bestimmte „Freund“ Implementierung beschränkt, fühlen sich jedoch freie Implementierung Besonderheiten hinweisen, wenn relevant]Verwenden von "friend" -Deklarationen für Komponententests. Schlechte Idee?

durch die offenen Fragen Lesen, ich auf das InternalsVisibleTo Attribut gestolpert:

gibt an, dass die Typen gewöhnlich nur sichtbar innerhalb der Baugruppe Strom sichtbar sind andere Baugruppe sind.

Die C# Programming Guide auf MSDN hat einen Abschnitt Friend Assemblies das beschreibt, wie das Attribut zu verwenden, um die Verwendung von internal Methoden und Arten auf eine andere Baugruppe zu ermöglichen.

Ich frage mich, ob es eine gute Idee wäre, dies zu verwenden, um eine "versteckte" Schnittstelle zum Instrumentieren einer Bibliothek für die Verwendung durch die Einheit Test Assembly zu erstellen. Es scheint die Kopplung in beiden Richtungen massiv zu erhöhen (Testcode in der Produktionsbaugruppe, intimes internes Wissen über die Produktionsbaugruppe im Testcode), aber andererseits könnte es bei der Erstellung feingranularer Tests helfen, ohne die öffentliche Schnittstelle zu überladen.

Welche Erfahrungen haben Sie beim Testen mit Friend-Deklarationen gemacht? War es deine Silver Bullet, oder hat der Todesmarsch begonnen?

Antwort

13

Ich habe diese Technik ausgiebig genutzt - es bedeutet, dass meine Komponententests Aspekte der Codebibliothek testen können, die für normale Verbraucher nicht sichtbar sind.

Während die Verwendung [InternalsVisibleTo] erhöht die Kopplung, glaube ich, dass der (geringe) Anstieg lohnt sich die Gewinne.

Meine Komponententests sind bereits eng mit dem getesteten Code gekoppelt - obwohl ich versuche, Tests zu schreiben, die bestimmte Ergebnisse, nicht spezifische Implementierungen durch Zugriff auf Dinge, die für normale Verbraucher nicht sichtbar sind, zu sichern, beschränke ich die Implementierung.

in die andere Richtung, die Kupplung ist minimal - das [InternalsVisibleTo] Attribut auf der Code-Zusammenstellung in hat, und einige Dinge in Kennzeichnung als interne anstelle von privaten (oder internen geschützt anstelle von geschützt) .

(Beachten Sie, dass ich hier keine Designänderungen bin ignorieren, die durch die Verwendung von Unit-Tests hervorgerufen werden, die eine ganz andere Diskussion ist.)

Das [InternalsVisibleTo] Attribut erfordert Ihre Baugruppen stark zu benennen. Wenn Sie dies nicht bereits tun, ist dies möglicherweise etwas mühsam, da eine stark benannte Assembly möglicherweise nur von anderen stark benannten Assemblys abhängt, was dazu führen kann, dass Sie mehrere Assemblys ändern müssen.

Das Attribut richtig zu bekommen kann ein bisschen fummelig sein, da es den öffentlichen Schlüssel Ihrer Testbaugruppe enthalten muss. IDesign hat eine nützliche Friend Assembly tool, die das Attribut in Ihrer Zwischenablage erstellt, bereit zum Einfügen. Empfohlen.

+0

Danke für den Hinweis auf starke Namensgebung! Ich war mir (noch) nicht dessen bewusst, aber da ich denke, dass alle meine Versammlungen stark nach Veröffentlichung benannt werden müssen, sehe ich das nicht als ein echtes Problem an. –

12

Es ist die einzige Verwendung, die ich jemals persönlich auf InternalsVisibleTo angewendet habe - und es war in der Tat sehr, sehr praktisch.

Ich sehe Komponententests nicht als Blackbox-Tests - sie sind bereits in gewissem Umfang an die Implementierung gekoppelt. Die Möglichkeit, interne Typen und Methoden zu testen, ermöglicht eine viel engere Fokussierung (kleinere Einheiten).

3

Ich denke, mit InternalsVisibleToAttribute zu aktivieren Einheitstests ist völlig in Ordnung. Meine "Unit" in "Unit Testing" ist eine Klasse, und dazu gehören internal Klassen, also möchte ich sie testen. I don't want to unit test private methods, obwohl.

Ich denke nicht, eine spezielle, private Schnittstelle nur für Tests zu erstellen, ist eine gute Idee. Einer der Werte von Komponententests ist, dass es Ihnen die Möglichkeit gibt, über die Schnittstelle zu Ihrer Klasse aus der Sicht eines Verbrauchers dieser Klasse nachzudenken. Die Bereitstellung einer Hintertür nimmt diesen Vorteil weg.

Meine Präferenz ist jedoch, meine Komponententests in derselben Baugruppe wie mein Produktionscode zu setzen. Es betrifft normalerweise nicht meine Kunden, aber es vereinfacht die Dinge für mich, also tue ich es. Wenn ich das mache, macht es die InternalsVisibleTo Frage weg.

3

In der Tat, Unit Testing ist die nur Verwendung, die ich in der Lage, mich selbst zu verwenden, um die InternalsVisibleToAttribute für verwenden konnte. Damit können Sie einen großen Teil Ihrer "privaten" Methoden als intern implementieren, um sie dem Einheitentest-Framework für ein invasiveres Testen von klasseninternen Invarianten zugänglich zu machen.

Ich hatte großen Erfolg mit dieser Technik. Wenn nichts anderes hilft, nähern Sie sich diesem mythischen Code-Coverage-Ziel an, indem Sie in Situationen, die sonst nicht zugänglich sind, private Methoden aufrufen können.

2

Ich denke, ein anderer legitimer Anwendungsfall kommt, wenn Sie separate Assemblys verwendet haben, wenn Sie älteren C++ - Code mit neueren C# -Code zusammenführen.

Wir haben die C++ Assemblies genommen, sie in C++/CLI konvertiert und dann neueren Code in C# implementiert. Wenn wir dies tun, würden wir immer noch "internal" für die Klassen/Methoden in C# verwenden, die nicht wirklich öffentlich sind, und diese dann dem alten Code als Freund-Assemblies zur Verfügung stellen.