by Andreas

.NET Unittest av private metoder – InternalsVisibleTo()

Programming

Unittesting av private metoder i en assembly ender enten ofte opp med at man midlertidig endrer dem til public, lager en intern main-metode i klassen som har tilgang – eller gjerne dropper hele testen (Robert Martin ville rullet seg i graven, og han er ikke engang død).

Det finnes forøvrig en mindre kjent måte å aksessere private (interne) metoder for gitte klasser (les: unittestklassen).

System.Runtime.CompilerServices.InternalsVisibleTo()

Kort fortalt gir du en navngitt assembly tilgang til alle metoder merket INTERNAL (som et alternativ til PRIVATE). Dette er spesielt nyttig i forbindelse med utvikling av Sharepoint-moduler hvor debugging er en tidkrevende prosess, men fungerer også for andre typer prosjekter. Mitt eksempel viser fremgangsmåte med signerte assemblier (inneholder en .snk-fil hvor vi kan finne public key).

Gitt at vi har et Sharepoint 2010 Visual Web Part-prosjekt og en unittestklasse i to separate assemblies. Vi trenger unittestassembliens public key, og om denne assemblien ikke er signert kan dette gjøres via prosjektets Properties -> Signing -> Sign this assembly (checkbox). Velg <New..> fra dropdownlista og gi den navnet key.snk. (Jeg valgte å ikke bruke noe passord)

Åpne Visual Studio Command Prompt (Start -> Microsoft Visual Studio 2010 -> Visual Studio Tools), naviger til directorien som key.snk ligger i (unittestprosjektet). Kjørt først en kommando for å eksportere public key fra .snk-filen, deretter skriv den ut til console:

sn -p key.snk BillingWebPartTest.PublicKeyOnly.snk
sn -tp BillingWebPartTest.PublicKeyOnly.snk

Du har da fått tak i unittestassembliens public key.

Denne må da legges inn i klassen med metodene som skal eksponeres til unittestassemblien – rett etter using-biten av klassen men FØR namespace deklareres legges attributten InternalsVisibleTo inn slik:

På denne måten vil assemblien BillingWebPartTest med gitt public key få tilgang til alle metoder merket internal:

internal SPListItem getSelectedItem()

Du kan da kalle de interne metodene fra unittestklassen som om de skulle være public:

BillingWebPartUserControl uc = new BillingWebPartUserControl();
uc.getSelectedItem(