Odkryłem, że istnieją tylko 3 sposoby testowania jednostkowego zależności (makiety / kodu pośredniczącego), które są statyczne w języku C # .NET:
Biorąc pod uwagę, że dwa z nich nie są darmowe, a jeden nie trafił w wersji 1.0, drwiny ze statycznych rzeczy nie są zbyt łatwe.
Czy to czyni metody statyczne i takie „złe” (w sensie testowania jednostkowego)? A jeśli tak, to dlaczego resharper chce, żebym zrobił coś, co może być statyczne, statyczne? (Zakładając, że resharper nie jest również „zły”).
Wyjaśnienie: Mówię o scenariuszu, w którym chcesz przetestować metodę, a metoda ta wywołuje metodę statyczną w innej jednostce / klasie. Według większości definicji testowania jednostkowego, jeśli pozwalasz testowanej metodzie wywoływać metodę statyczną w innej jednostce / klasie, to nie jesteś testem jednostkowym, to testujesz integrację . (Przydatne, ale nie test jednostkowy.)
źródło
Odpowiedzi:
Patrząc na inne odpowiedzi tutaj, myślę, że może być pewne zamieszanie między metodami statycznymi, które utrzymują stan statyczny lub powodują skutki uboczne (co wydaje mi się naprawdę złym pomysłem), a metodami statycznymi, które jedynie zwracają wartość.
Metody statyczne, które nie utrzymują żadnego stanu i nie powodują żadnych skutków ubocznych, powinny być łatwo testowane jednostkowo. W rzeczywistości uważam takie metody za „funkcjonalność biedaka” programowania funkcjonalnego; przekazujesz metodę obiekt lub wartość i zwraca obiekt lub wartość. Nic więcej. Nie rozumiem, w jaki sposób takie metody wpłynęłyby w ogóle na testy jednostkowe.
źródło
Wygląda na to, że mylisz dane statyczne i metody statyczne . Resharper, jeśli dobrze pamiętam, zaleca tworzenie
private
metod w klasie statycznych, jeśli można je tak uczynić - uważam, że daje to niewielką korzyść w zakresie wydajności. To nie polecam dokonanie „wszystko, co może być” statyczne!Nie ma nic złego w metodach statycznych i są one łatwe do przetestowania (o ile nie zmieniają żadnych danych statycznych). Na przykład pomyśl o bibliotece Maths, która jest dobrym kandydatem do klasy statycznej z metodami statycznymi. Jeśli masz (wymyśloną) metodę taką:
to jest doskonale testowalne i nie ma skutków ubocznych. Po prostu sprawdzasz, że kiedy wpadasz, powiedzmy 20, wrócisz 400. Nie ma problemu.
źródło
System.Math
), Nie wspominając o obfitości statycznych metod fabrycznych itp. Ponadto nigdy nie będziesz w stanie używać żadnych metod rozszerzania itp. Faktem jest, że takie proste funkcje są takie podstawowe dla języków współczesnych. Możesz je przetestować w izolacji (ponieważ na ogół będą deterministyczne), a następnie bez obaw używać ich w swoich klasach. To nie jest problem!Jeśli prawdziwe pytanie brzmi „Jak przetestować ten kod?”:
Następnie po prostu refaktoryzuj kod i wstaw jak zwykle wywołanie klasy statycznej w następujący sposób:
źródło
Statyka niekoniecznie jest zła, ale może ograniczyć twoje możliwości, jeśli chodzi o testowanie jednostkowe z podróbkami / próbkami / skrótami.
Istnieją dwa ogólne podejścia do kpin.
Pierwszy (tradycyjny - wdrożony przez RhinoMocks, Moq, NMock2; w tym obozie również znajdują się ręczne makiety i odcinki) opiera się na szwach testowych i wstrzykiwaniu zależności. Załóżmy, że testujesz jednostkowo jakiś kod statyczny i ma on zależności. W tak skonstruowanym kodzie często zdarza się, że statyka tworzy własne zależności, odwracając inwersję zależności . Wkrótce odkryjesz, że nie możesz wstrzykiwać fałszywych interfejsów do testowanego kodu zaprojektowanego w ten sposób.
Drugi (próbować czegokolwiek - wdrożony przez TypeMock, JustMock i Moles) opiera się na API profilowania .NET . Może przechwycić dowolną instrukcję CIL i zastąpić fragment kodu fałszywym. Pozwala to TypeMock i innym produktom w tym obozie wyśmiewać wszystko: statykę, zapieczętowane klasy, prywatne metody - rzeczy, które nie zostały zaprojektowane do testowania.
Trwa debata między dwiema szkołami myślenia. Mówi się, że przestrzegaj zasad SOLID i projektuj testowalność (często obejmuje to łatwość w statywie). Drugi mówi: kup TypeMock i nie martw się.
źródło
Sprawdź to: „Metody statyczne to śmierć dla testowalności” . Krótkie streszczenie argumentu:
Aby przeprowadzić test jednostkowy, musisz wziąć mały fragment kodu, ponownie powiązać jego zależności i przetestować go w izolacji. Jest to trudne w przypadku metod statycznych, nie tylko w przypadku, gdy uzyskują dostęp do stanu globalnego, ale nawet jeśli wywołują inne metody statyczne.
źródło
Prosta prawda rzadko uznawana jest taka, że jeśli klasa zawiera zależną od kompilatora zależność od innej klasy, nie można jej przetestować w oderwaniu od tej klasy. Możesz sfałszować coś, co wygląda jak test, i pojawi się w raporcie, jakby to był test.
Ale nie będzie miał kluczowych właściwości definiujących test; porażki, gdy coś jest nie tak, przemijanie, gdy mają rację.
Dotyczy to wszelkich wywołań statycznych, wywołań konstruktora oraz wszelkich odniesień do metod lub pól, które nie są dziedziczone z klasy podstawowej lub interfejsu . Jeśli nazwa klasy pojawia się w kodzie, jest to zależność widoczna dla kompilatora i bez niej nie można poprawnie przetestować. Każda mniejsza porcja po prostu nie jest prawidłową jednostką do przetestowania . Każda próba potraktowania go tak, jakby był, przyniesie wyniki nie bardziej znaczące niż napisanie małego narzędzia do emitowania kodu XML używanego przez środowisko testowe w celu powiedzenia „test pozytywny”.
Biorąc to pod uwagę, istnieją trzy opcje:
zdefiniuj testowanie jednostkowe jako testowanie jednostki złożonej z klasy i jej zakodowanych zależności. Działa to, pod warunkiem, że unikniesz zależności cyklicznych.
nigdy nie twórz zależności czasu kompilacji między klasami, za które odpowiadasz za testowanie. Działa to, pod warunkiem, że nie przeszkadza ci wynikowy styl kodu.
nie testuj jednostki, zamiast tego test integracji. Który działa, pod warunkiem, że nie powoduje konfliktu z czymś innym, do czego należy użyć terminu testowanie integracji.
źródło
Math.Pi
do metody nie czyni testu integracji z żadnej rozsądnej definicji.Nie ma na to dwóch sposobów. Sugestie ReSharpera i kilka przydatnych funkcji języka C # nie byłyby używane tak często, gdybyś pisał izolowane testy jednostek atomowych dla całego kodu.
Na przykład, jeśli masz metodę statyczną i musisz ją zlikwidować, nie możesz tego zrobić, chyba że użyjesz struktury izolacji opartej na profilu. Obejściem kompatybilnym z połączeniem jest zmiana początku metody używania notacji lambda. Na przykład:
PRZED:
PO:
Oba są kompatybilne z połączeniami. Dzwoniący nie muszą się zmieniać. Ciało funkcji pozostaje takie samo.
Następnie w kodzie testu jednostkowego możesz w ten sposób wyciąć to wywołanie (zakładając, że należy ono do klasy o nazwie Baza danych):
Po zakończeniu należy go zastąpić oryginalną wartością. Możesz to zrobić za pomocą try / wreszcie lub, w trakcie czyszczenia testu jednostkowego, tego, który jest wywoływany po każdym teście, napisz kod taki jak ten:
który ponownie wywoła statyczny inicjalizator twojej klasy.
Lambda Funcs nie są tak bogate w wsparcie jak zwykłe metody statyczne, więc takie podejście ma następujące niepożądane skutki uboczne:
Powiedzmy jednak, że całkowicie unikasz statyki i zamieniasz ją na metodę instancji. Nadal nie można go wyśmiewać, chyba że metoda jest wirtualna lub zaimplementowana jako część interfejsu.
Tak więc w rzeczywistości każdy, kto sugeruje rozwiązanie problemu umieszczania metod statycznych, ma uczynić je metodami instancji, byłyby także przeciwne metodom instancji, które nie są wirtualne lub stanowią część interfejsu.
Dlaczego więc C # ma metody statyczne? Dlaczego dopuszcza metody instancji innych niż wirtualne?
Jeśli użyjesz jednej z tych „funkcji”, po prostu nie będziesz mógł stworzyć izolowanych metod.
Kiedy ich używasz?
Używaj ich do każdego kodu, którego nie spodziewasz się, że ktokolwiek zechce go usunąć. Kilka przykładów: metoda Format () klasy String, metoda WriteLine () klasy Console, metoda Cosh () klasy Math
I jeszcze jedno. Większość ludzi nie będzie się tym przejmować, ale jeśli możesz o wykonanie połączenia pośredniego, to kolejny powód, aby unikać metod instancji. Zdarzają się przypadki, gdy jest to hit wydajności. Właśnie dlatego istnieją metody inne niż wirtualne.
źródło
R # nie jest jedynym narzędziem, które sprawi, że ta sugestia. Analiza FxCop / MS Code również zrobi to samo.
Ogólnie powiedziałbym, że jeśli metoda jest statyczna, ogólnie powinna być również możliwa do przetestowania. Daje to trochę do myślenia przy projektowaniu i prawdopodobnie więcej dyskusji niż teraz w moich palcach, więc cierpliwie czekam na słabe głosy i komentarze ...;)
źródło
Widzę, że po długim czasie nikt jeszcze nie stwierdził naprawdę prostego faktu. Jeśli resharper mówi mi, że mogę uczynić metodę statyczną, oznacza to dla mnie ogromną rzecz, słyszę jego głos mówiący: „hej, ty, te logiki nie są OBOWIĄZKOWĄ klasą do obsługi, więc powinna pozostać na zewnątrz w jakiejś klasie pomocniczej czy coś ".
źródło
Jeśli metoda statyczna jest wywoływana z innej metody , nie można zapobiec ani zastąpić takiego wywołania. Oznacza to, że te dwie metody tworzą jedną Jednostkę; Test jednostkowy dowolnego rodzaju sprawdza je oba.
A jeśli ta statyczna metoda komunikuje się z Internetem, łączy bazy danych, wyświetla wyskakujące okienka GUI lub w inny sposób przekształca test Jednostki w kompletny bałagan, robi to bez żadnego łatwego obejścia. Metoda wywołująca taką metodę statyczną nie jest testowalna bez refaktoryzacji, nawet jeśli zawiera wiele kodu czysto obliczeniowego, który bardzo skorzystałby na testowaniu jednostkowym.
źródło
Wierzę, że Resharper daje ci wskazówki i stosuje wytyczne kodowania, z którymi został skonfigurowany. Kiedy użyłem Resharpera i powiedział mi, że metoda powinna być statyczna, to na pewno będzie to metoda prywatna, która nie działa na żadne zmienne instancji.
Jeśli chodzi o testablity, ten scenariusz nie powinien stanowić problemu, ponieważ i tak nie powinieneś testować metod prywatnych.
Jeśli chodzi o testowalność metod statycznych, które są publiczne, to testy jednostkowe stają się trudne, gdy metody statyczne dotykają stanu statycznego. Osobiście ograniczyłbym to do minimum i używałbym metod statycznych jako czystych funkcji, o ile to możliwe, tam gdzie wszelkie zależności są przekazywane do metody, którą można kontrolować za pomocą urządzenia testowego. Jest to jednak decyzja projektowa.
źródło