2013-02-20 17 views
9

W odniesieniu do testów jednostkowych, uczono mnie, że kod produkcyjny nie powinien zawierać kodu związanego z testem.Czy istnieją interfejsy jednego implementatora do testowania urządzenia przeciwdziałającego?

Cóż, mam wrażenie, że łamam tę zasadę za każdym razem, gdy próbuję przeprowadzić test jednostkowy.

Mam klasy wewnętrznej do mojego zespołu, Xyzzy. Chcę zależności wstrzyknąć go do innej klasy, a następnie po prostu go zamknąć, aby przetestować drugą klasę w izolacji, więc mam interfejs, IXyzzy. Ups, teraz mam kod w produkcji, który jest naprawdę tylko do testów. Co gorsza, mam niby poszedł na co interfejs (opisuje co za wdrażająca może zrobić, a nie to, co jest). Publiczny interfejs Xyzzy i IXyzzy są dokładnie takie same i nikt inny (z wyjątkiem skrótów) nie implementuje IXyzzy.

To wydaje mi się złe.

Mogę utworzyć abstrakcyjną klasę bazową lub utworzyć wszystkie publiczne metody, które chcę przetestować na Xyzzy Overridable/virtual, ale to też nie działa, ponieważ Xyzzy nie jest przeznaczony do dziedziczenia iz perspektywy YAGNI nigdy nie będzie być odziedziczonym po.

jest tworzenie interfejsów pojedynczych Realizator wyłącznie do celów testowania anty-wzorzec? Czy istnieją lepsze alternatywy?

Odpowiedz

7

Nie jest źle mieć kod tylko do testów. Jest to normalne, tak jak kod produkcyjny zawiera funkcje, które są tworzone tylko w celu debugowania i monitorowania produkcji. Nie ma wyraźnego powodu, dla którego powinno to być zabronione. Kod powinien obsługiwać wszystkie aspekty stylu życia aplikacji. Testowanie to kolejna część cyklu życia.

W tym sensie twoje podejście do korzystania z interfejsów jest poprawne. Jeśli sprawisz, że reszta aplikacji produkcyjnej również skorzysta z interfejsu (a nie konkretnej klasy, choć jest tylko jedna), będzie to architektura solidna.

mam niby poszedł na co interfejs (opisuje co za wdrażająca może zrobić, a nie, co to jest)

nie dostać punkt tutaj ponieważ interfejs ma co opisywać obiekt może zrobić. Istnienie tylko jednej konkretnej (produkcyjnej) implementacji nie niszczy tej właściwości.

Jeśli o tym pomyślisz, każda klasa ma "interfejs" w luźniejszym tego słowa znaczeniu: publiczny podpis wszystkich metod eksponuje interfejs, który klasa wspiera na zewnątrz. To, czy interfejs .NET jest zaimplementowany, czy nie, jest tylko szczegółem. Klasa nadal składa te same obietnice na zewnątrz.

+1

Bardzo prawdziwe, wiele moich interfejsów, np. 'IRequestor', opisać co robi;) –

3

Z mojego doświadczenia, to jest dość typowe dla rozwoju .NET, wynikające z faktu, że metoda nadrzędnym jest na zasadzie opt-in; jeśli chcesz wyśmiać zależność, potrzebujesz albo interfejsu, albo obiektu, którego metody są wszystkie wirtualne.

w języku Java, gdzie jak każda metoda jest przeciążać interfejsy single-wdrożeniowe są rzeczywiście antywzorzec projektowy i dobrych deweloperów wezwie go.

dalej robić to, co robisz - cokolwiek grzech jesteś popełnienie jest, moim zdaniem, dłoń zrównoważone przez korzyści wynikające z Twojego testów jednostkowych!

+2

Uzgodnione korzyści z testów jednostkowych;) Interesujący artykuł na temat tego, dlaczego C# nie ma domyślnie wirtualnych metod instancji: http://geekswithblogs.net/madhawa/archive /2006/09/17/91418.aspx –

+0

Fajny link, dzięki! – Ben

2

Tak, jest to anty-wzór.Wzór byłby "rozwiązaniem wspólnego problemu w określonym kontekście". Ale w tym przypadku mamy do czynienia z obejściem, a nie rozwiązaniem.

Problem polega na tym, że trzeba wykonać izolację , która ma zostać przetestowana na podstawie (niektórych) jej zależności, tak aby implementacja tych zależności nie była konieczna przy pisaniu testów jednostkowych. Ogólne i prawdziwe rozwiązanie tego problemu nazywa się "szyderstwem", w którym autor testu może określić, jakie zachowanie jest potrzebne od wyśmiewanych zależności.

W przeciwieństwie do tego, zmuszanie programisty do tworzenia niepotrzebnych oddzielnych interfejsów lub deklarowanie metod jako virtual, jest tylko obejściem dla technicznej niezdolności do czystego odizolowania jednostki od innych.

. NET, istnieje kilka narzędzi szyderstwa, które zapewniają tę zdolność izolacji, a mianowicie TypeMock Isolator, JustMock i MS Fakes. Inne języki/platformy (w tym Java, Ruby i Python) mają własne narzędzia o podobnej sile ekspresji.

+1

Istnieje dobre pytanie na SO, które mówi o ostatniej części odpowiedzi: [Czy korzystanie z interfejsów Soley w celu ułatwienia stymulacji i wyszydzania w testach jednostkowych jest teraz przestarzałe?] (Http://stackoverflow.com/q/3869002/945456) –