Klasy internal a testowanie jednostkowe

Często mam okazję pracować nad projektami, które udostępniają bardzo wąski interfejs na zewnątrz, mimo że zawierają w sobie dużo nietrywialnej logiki. Krótko mówiąc – powstaje bardzo mało klas publicznych i dość dużo klas internal. Testy jednostkowe zawsze umieszczam w oddzielnym projekcie. Przez długi okres, za każdym razem kiedy czułem potrzebę napisania testów dla klasy internal, robiłem to co sprawiało mi najmniej problemów – przekształcałem klasę na publiczną. W takich sytuacjach miałem jednak poczucie, że coś jest nie tak. Przecież to właśnie ja stworzyłem wcześniej tę klasę i z jakiś względów postanowiłem, że nie będzie ona widoczna poza projektem. Co powinniśmy zrobić w takim przypadku? Sam wciąż szukam odpowiedzi na to pytanie.

Czytałem wiele opinii na ten temat i zdania są podzielone. Jedni uważają, że należy testować tylko i wyłącznie to, co jest publiczne. Ciężko jest mi się z nimi zgodzić. Spotkałem się z projektami, gdzie takie podejście znacznie utrudnia pracę. Łatwiej jest dokładnie pokryć testami mniejsze komponenty, a dopiero później przejść do tych większych.

Chciałbym zachować przy klasie modyfikator internal i być w stanie napisać do niej testy. Powstaje pytanie jak można to zrobić, jeżeli w ogóle jest to możliwe. Znane są mi trzy metody. Postaram się je krótko przedstawić w subiektywnej kolejności od najgorszej do najlepszej.

  1. Refleksja
    Moim zdaniem najsłabsze rozwiązanie. Ciężkie w tworzeniu, zrozumieniu i utrzymywaniu. Chyba jedyna zaleta jest taka, że da się zrobić to czego potrzebuję.
  2. Dyrektywa #if
    Znacznie wygodniejsze jeżeli chodzi o pracę z testami, ale trochę zaśmieca nasz kod źródłowy. Musimy ją zastosować dla każdej klasy internal, którą będziemy chcieli testować. To rozwiązanie wymaga również dodania nowej flagi (np. UNITTESTS) do opcji kompilatora.
  3. InternalsVisibleToAttribute
    Najbardziej eleganckie podejście. Wystarczy dodać odpowiednią linijkę w pliku AssemblyInfo.cs. Dzięki temu klasy internal stają się widoczne dla konkretnej assembly (w moim przypadku dla projektu z unit testami).

Celem tego posta nie jest nakłanianie programistów do testowania klas internal, a jedynie przedstawienie dostępnych metod oraz moich własnych refleksji na ten temat. Wiele osób uważa, że nie powinno się tego robić i na pewno warto się zastanowić zanim zaczniemy wprowadzać jakiekolwiek zmiany w naszych projektach.

2 komentarzy dotyczących “Klasy internal a testowanie jednostkowe

  1. Korzystam tylko z podejścia trzeciego. Karcę każego, kto odważy się ruszyć refleksję w taki sposób 😉
    O drugim nie słyszałem, więc nawe nie wiedziałem do końca, że tak można.

Dodaj komentarz

Twój adres email nie będzie opublikowany. Pola wymagane zostały oznaczone *