Beim Schreiben von Unittests bin ich mal wieder darüber gestolpert, dass jemand speziell für die Unittests Getter und Setter angelegt hat, da er auf die privaten Variablen der Klasse nicht zugreifen konnte. Im Prinzip hat er damit für seinen Unittest die internen Variablen dann über den Zugriffsmodifizierer public dann doch wieder sichtbar gemacht, wenn auch nur indirekt. Das ist so natürlich nicht gewollt, denn sonst hätte man gleich den Zugriff auf die internen Variablen erlauben können. Vielleicht noch kurz zur Erklärung: unsere Unittests sind immer in eigenständige Assemblies ausgelagert, sodass wir von Außen auf die zu testenden Klassen zugreifen müssen. Das macht auch Sinn, da die Unittests in dem Kompilat nicht enthalten sein sollen. Wie kann man das Problem also lösen?
Das .NET Framework bietet dafür das Attribut InternalsVisibleTo aus dem Namespace System.Runtime.CompilerServices an. Um nun die internal Methoden, Variablen und Properties freizugeben, wird das Attribut in die AssemblyInfo.cs des zu testenden Projekts eingefügt.
1 |
[assembly:InternalsVisibleTo("UnittestAssemblyName")] |
Danach kann man mit dem im InternalsVisibleTo-Attribut angegeben Assembly seine Unittests auf den Klassen durchführen ohne alles Zugriffsmodifizierer auf public zu setzen.
Solltet ihr eure Assemblies signieren, muss das einzufügende Attribut um den Public Key des zugreifenden Assemblies erweitert werden. Zusätzlich muss außerdem das zugreifende Assembly signiert werden. Der Eintrag in der AssemblyInfo.cs sieht dann so aus:
1 2 3 4 5 6 7 8 9 10 |
[assembly: InternalsVisibleTo("UnittestAssemblyName, PublicKey=002500000590000095" + "0000000703000000240000525351310005000" + "002000100bf8c42fcd44838d89e245ab35bf7" + "3bf2616707feea296709559b4de903fe95aa3" + "3d3729977c3184aa7d7b84c7557cd87e435d5" + "6bef8621bcb63b59c00c89bd83aa63c4fced4" + "722da73eec2543dc00f9529c3a1bbb4103382" + "f1d894d5f44e9f0203c474dce9f5b457a5dfe" + "fd9f920d8682ed6dfce0a81e97bd9b176526a" + "27e1b3")] |
Das ist natürlich nur eine Herangehensweise, aber – wie ich finde – eine doch recht elegante. Wie macht ihr das in euren Unittests? Habt ihr eine ähnliche Vorgehensweise oder schreibt ihr einfach gar keine ;-)?