Der er basalt set 4 måder at teste private metoder på:
- Marker metoden som internal
- Indlejret testklasse
- Refleksion
- Undgå det
1 – Markerer man metoden som internal, og samtidig angiver test-assembly'en som ven, kan man få adgang til den fra test metoderne. Metoden er brugbar, men man bryder man indkapslingen. Der er godt nok ikke andre assembly'er der kan tilgå metoderne, men internt, har man åbnet adgangen fra alle andre klasser. Det lugter lidt...
Man markerer sin assembly som ven, ved at føje en InternalsVisibleToAttribute til assembly'en. Det gøres nemmest i AssemblyInfo.cs filen:
[code=csharp] [assembly: InternalsVisibleTo("myTest")] [/code]
2 – Man kan indlejre sin testklasse I selve klassen, som man ønsker at teste. På den måde, har man fuld adgang til alle medlemmer. Det indebærer selvfølgelig at man får spredt sine tests ud over det hele, og man kan få store problemer med overskueligheden. Hvad er test og hvad er produktion?
3 – Man kan bruge refleksion, og Invoke metoden med MethodInfo klassen.
[code=csharp] [TestMethod]
public void Test_privat_metode()
{
MyClass m = new MyClass();
MethodInfo mi =
typeof(MyClass).GetMethod("GetMessage", BindingFlags.NonPublic | BindingFlags.Instance);
object value = mi.Invoke(m, new object[] { 1 });
Assert.AreEqual("Hello!", value);
} [/code]
Fordelen ved refleksion er: at man undgår at bryde indkapslingen, og at man undgår at fylde sin produktionskode med test-kode. Ulempen er at man få noget følsom test-kode, da man jo angiver metodenavne i strenge. En RenameMethod refactoring, vil afstedkomme at alle tests af den metode vil fejle.
4 – Undgå det. Man skal aldrig bryde indkapsling for at kunne teste. En klasses funktionalitet, bør kunne testes gennem dens offentlige interface. Husk på at testen skal teste funktionalitet, og ikke implementering. Hvis ikke, er det sandsynligvis en code-smell, der forsøger at fortælle dig noget. F.eks. at du skal uddrage en ny klasse til at dække funktionaliteten.
Der er selvfølgelig steder, hvor man bare er nød til at bryde denne indkapsling, for at kunne foretage sine tests, men jeg mener at disse tilfælde er uhyre sjældne, og bør afstedkomme en nærmere undersøgelse.
Der er selvfølgelig ikke et rigtigt svar til hvordan/om man skal teste private metoder. Det kommer i høj grad an på situationen. Jeg hælder nok selv mest til metode 4...
Carry On Implementing…