Jestem nowy w testowaniu jednostkowym i ciągle słyszę słowa „pozorowane obiekty” rzucane wokół. Mówiąc prostym językiem, czy ktoś może wyjaśnić, czym są pozorowane obiekty i do czego są zwykle używane podczas pisania testów jednostkowych?
unit-testing
mocking
agentbanks217
źródło
źródło
Odpowiedzi:
Ponieważ mówisz, że jesteś nowy w testowaniu jednostkowym i prosiłeś o pozorowane obiekty w „terminach laika”, spróbuję użyć przykładu laika.
Testów jednostkowych
Wyobraź sobie testy jednostkowe dla tego systemu:
Ogólnie łatwo jest wyobrazić sobie testowanie komponentu niskiego poziomu, takiego jak
cook
:Kierowca testowy po prostu zamawia różne dania i sprawdza, czy kucharz zwraca właściwe danie dla każdego zamówienia.
Trudniej jest przetestować środkowy komponent, taki jak kelner, który wykorzystuje zachowanie innych komponentów. Naiwny tester mógłby przetestować komponent kelnera w ten sam sposób, w jaki testowaliśmy komponent cook:
Kierowca testowy zamawiał różne dania i upewniał się, że kelner zwraca właściwe danie. Niestety oznacza to, że ten test komponentu kelnerskiego może zależeć od prawidłowego zachowania się komponentu gotującego. Zależność ta jest jeszcze gorsza, jeśli składnik gotowania ma jakiekolwiek cechy nieprzyjazne dla testów, takie jak zachowanie niedeterministyczne (menu zawiera niespodziankę szefa kuchni jako danie), wiele zależności (kucharz nie będzie gotować bez całego personelu) lub wiele zasoby (niektóre dania wymagają drogich składników lub gotowanie trwa godzinę).
Ponieważ jest to test kelnerski, najlepiej byłoby przetestować tylko kelnera, a nie kucharza. W szczególności chcemy mieć pewność, że kelner prawidłowo przekazuje zamówienie klienta kucharzowi i prawidłowo dostarcza potrawy kucharza do klienta.
Testowanie jednostkowe oznacza niezależne testowanie jednostek, więc lepszym podejściem byłoby wyodrębnienie testowanego komponentu (kelnera) za pomocą tego, co Fowler nazywa testowymi dublami (manekiny, stuby, podróbki, mocky) .
Tutaj kucharz testowy jest „w zmowie” z kierowcą testowym. Idealnie, testowany system jest zaprojektowany tak, aby kucharz testowy mógł być łatwo zastąpiony ( wstrzyknięty ) do pracy z kelnerem bez zmiany kodu produkcji (np. Bez zmiany kodu kelnera).
Mock Objects
Teraz gotowanie testowe (test podwójny) można zaimplementować na różne sposoby:
Zobacz artykuł Fowlera, aby uzyskać więcej informacji na temat podróbek vs niedopałków vs mocków vs manekinów , ale na razie skupmy się na pozorowanym kucharzu.
Duża część testowania jednostkowego składnika kelnera koncentruje się na tym, jak kelner współdziała z komponentem Cook. Podejście oparte na próbach skupia się na pełnym określeniu, czym jest właściwa interakcja i wykrywaniu, kiedy jest nie tak.
Obiekt pozorowany z góry wie, co ma się wydarzyć podczas testu (np. Która z jego metod wywoła wywołanie itp.), A obiekt pozorowany wie, jak ma zareagować (np. Jaką wartość zwracaną ma dostarczyć). Makieta wskaże, czy to, co naprawdę się dzieje, różni się od tego, co powinno się wydarzyć. Dla każdego przypadku testowego można by stworzyć od podstaw niestandardowy obiekt pozorowany, aby wykonać oczekiwane zachowanie dla tego przypadku testowego, ale frameworka do pozorowania stara się umożliwić jasne i łatwe wskazanie takiej specyfikacji zachowania bezpośrednio w przypadku testowym.
Rozmowa wokół testu opartego na próbach może wyglądać następująco:
Ale ponieważ nasz kelner jest nowy, może się tak stać:
lub
Może być trudno dostrzec różnicę między pozorowanymi obiektami i kodami pośredniczącymi bez kontrastującego przykładu opartego na stubach, ale ta odpowiedź jest już zbyt długa :-)
Należy również zauważyć, że jest to dość uproszczony przykład i że frameworki do pozorowania pozwalają na dość wyrafinowane specyfikacje oczekiwanego zachowania komponentów w celu obsługi kompleksowych testów. Więcej informacji można znaleźć w materiałach na temat pozorowanych obiektów i fałszywych struktur.
źródło
Mock Object to obiekt, który zastępuje rzeczywisty obiekt. W programowaniu obiektowym pozorowane obiekty to symulowane obiekty, które naśladują zachowanie rzeczywistych obiektów w kontrolowany sposób.
Programista komputerowy zazwyczaj tworzy pozorowany obiekt, aby przetestować zachowanie innego obiektu, w podobny sposób, w jaki projektant samochodu używa manekina do testów zderzeniowych do symulacji dynamicznego zachowania człowieka w zderzeniu pojazdu.
http://en.wikipedia.org/wiki/Mock_object
Obiekty pozorowane umożliwiają konfigurowanie scenariuszy testowych bez obciążania dużych, nieporęcznych zasobów, takich jak bazy danych. Zamiast wywoływać bazę danych do testowania, możesz symulować swoją bazę danych przy użyciu pozorowanego obiektu w testach jednostkowych. To uwalnia Cię od konieczności konfigurowania i niszczenia prawdziwej bazy danych, aby przetestować tylko jedną metodę w swojej klasie.
Słowo „Mock” jest czasami błędnie używane zamiennie z „Stub”. Tutaj opisano różnice między tymi dwoma słowami . Zasadniczo, makieta to obiekt pośredniczący, który zawiera również oczekiwania (tj. „Potwierdzenia”) dotyczące właściwego zachowania testowanego obiektu / metody.
Na przykład:
Zauważ, że obiekty
warehouse
imailer
makiety są zaprogramowane z oczekiwanymi wynikami.źródło
Mockowe obiekty to symulowane obiekty, które naśladują zachowanie prawdziwych. Zwykle piszesz obiekt pozorowany, jeśli:
źródło
Obiekt Mock jest jednym z rodzajów Double Test . Używasz mockobjects do testowania i weryfikowania protokołu / interakcji testowanej klasy z innymi klasami.
Zwykle będziesz w pewnym sensie „program” lub „rejestrować” oczekiwania: wywołania metod, których oczekujesz od klasy względem obiektu bazowego.
Załóżmy na przykład, że testujemy metodę usługi, aby zaktualizować pole w widżecie. I że w twojej architekturze jest WidgetDAO, który zajmuje się bazą danych. Rozmowa z bazą danych jest powolna, a jej konfigurowanie i późniejsze czyszczenie jest skomplikowane, dlatego będziemy kpić z Widgetu
zastanówmy się, co usługa musi zrobić: powinna pobrać Widget z bazy danych, coś z tym zrobić i ponownie zapisać.
Czyli w pseudojęzyku z pseudo-próbną biblioteką mielibyśmy coś takiego:
W ten sposób możemy łatwo przetestować rozwój klas zależnych od innych klas.
źródło
Gorąco polecam świetny artykuł Martina Fowlera wyjaśniający, czym dokładnie są mocks i czym różnią się od stubów.
źródło
Podczas testowania jednostkowego jakiejś części programu komputerowego najlepiej byłoby przetestować tylko zachowanie tej określonej części.
Na przykład spójrz na poniższy pseudokod z wyimaginowanego fragmentu programu, który używa innego programu do wywołania funkcji print:
Gdybyś to testował, chciałbyś głównie przetestować część, która sprawdza, czy użytkownik jest Fredem, czy nie. Naprawdę nie chcesz testować
Printer
części rzeczy. To byłby kolejny test.W tym miejscu pojawiają się pozorowane obiekty. Udają inne rodzaje rzeczy. W takim przypadku użyłbyś Mocka,
Printer
aby działał jak prawdziwa drukarka, ale nie robiłby niewygodnych rzeczy, takich jak drukowanie.Istnieje kilka innych typów udawanych obiektów, które nie są makietami. Główną rzeczą, która sprawia, że Mocks Mocks jest to, że można je skonfigurować za pomocą zachowań i oczekiwań.
Oczekiwania pozwalają Twojemu Mockowi wywołać błąd, gdy jest używany nieprawidłowo. W powyższym przykładzie możesz chcieć mieć pewność, że Printer jest wywoływana z HelloFred w przypadku testowym „user is Fred”. Jeśli tak się nie stanie, Twój Mock może Cię ostrzec.
Zachowanie w Mocks oznacza, że na przykład Twój kod zrobił coś takiego:
Teraz chcesz przetestować, co robi twój kod, gdy wywoływana jest Printer i zwraca SaidHello, więc możesz skonfigurować Mocka, aby zwracał SaidHello, gdy jest wywoływany z HelloFred.
Jednym z dobrych źródeł na ten temat jest post Martina Fowlersa Mocks Aren't Stubs
źródło
Obiekty makiety i obiekty pośredniczące są kluczową częścią testów jednostkowych. W rzeczywistości przechodzą długą drogę, aby upewnić się, że testujesz jednostki , a nie grupy jednostek.
Krótko mówiąc, używasz stubów, aby zerwać zależność SUT (System Under Test) od innych obiektów i makiet, aby to zrobić, i sprawdzić, czy SUT wywołał pewne metody / właściwości w zależności. Wracamy do fundamentalnych zasad testowania jednostkowego - testy powinny być czytelne, szybkie i niewymagające konfiguracji, co może oznaczać użycie wszystkich prawdziwych klas.
Ogólnie możesz mieć więcej niż jeden kod pośredniczący w swoim teście, ale powinieneś mieć tylko jeden próbny. Dzieje się tak, ponieważ celem mocka jest weryfikacja zachowania, a twój test powinien testować tylko jedną rzecz.
Prosty scenariusz z użyciem C # i Moq:
W powyższym przykładzie użyłem Moq do zademonstrowania stubów i mocków. Moq używa tej samej klasy dla obu -
Mock<T>
co sprawia, że jest to nieco zagmatwane. Niezależnie od tego, w czasie wykonywania test zakończy się niepowodzeniem, jeślioutput.Write
nie zostanie wywołany z danymi asparameter
, natomiast niepowodzenie wywołaniainput.Read()
nie zakończy się niepowodzeniem.źródło
Jak sugerowała inna odpowiedź poprzez odsyłacz do „ Mocks to not Stubs ”, makiety są formą „testowego podwójnego” używanego zamiast prawdziwego obiektu. To, co odróżnia je od innych form podwójnych testów, takich jak obiekty pośrednie, polega na tym, że inne podwójne testy testowe oferują weryfikację stanu (i opcjonalnie symulację), podczas gdy makiety oferują weryfikację zachowania (i opcjonalnie symulację).
Za pomocą kodu pośredniczącego możesz wywołać kilka metod na kodeksie w dowolnej kolejności (lub nawet w sposób powtarzalny) i określić powodzenie, jeśli kod pośredniczący przechwycił zamierzoną wartość lub stan. Natomiast obiekt pozorowany oczekuje wywołania bardzo specyficznych funkcji, w określonej kolejności, a nawet określoną liczbę razy. Test z pozorowanym obiektem zostanie uznany za „nieudany” po prostu dlatego, że metody zostały wywołane w innej kolejności lub liczniku - nawet jeśli pozorowany obiekt miał poprawny stan po zakończeniu testu!
W ten sposób pozorowane obiekty są często uważane za ściślej powiązane z kodem SUT niż obiekty pośredniczące. To może być dobre lub złe, w zależności od tego, co próbujesz zweryfikować.
źródło
Częścią sensu używania obiektów pozorowanych jest to, że nie muszą one być tak naprawdę implementowane zgodnie ze specyfikacją. Mogą po prostu udzielić fałszywych odpowiedzi. Np. Jeśli musisz zaimplementować komponenty A i B i oba „wywołują” (współdziałają) ze sobą, to nie możesz testować A, dopóki B nie zostanie zaimplementowane i odwrotnie. W programowaniu opartym na testach jest to problem. Więc tworzysz pozorowane („fikcyjne”) obiekty dla A i B, które są bardzo proste, ale dają jakąś odpowiedź, gdy wchodzą w interakcję. W ten sposób możesz zaimplementować i przetestować A przy użyciu obiektu pozorowanego dla B.
źródło
Dla php i phpunit jest dobrze wyjaśnione w dokumentacji phpunit. zobacz tutaj dokumentację phpunit
W prostych słowach obiekt mockujący jest po prostu fikcyjnym obiektem twojego oryginalnego i zwraca swoją zwracaną wartość, ta zwracana wartość może być użyta w klasie testowej
źródło
To jedna z głównych perspektyw testów jednostkowych. tak, próbujesz przetestować swoją pojedynczą jednostkę kodu, a wyniki testu nie powinny mieć związku z zachowaniem innych komponentów bean lub obiektów. więc powinieneś kpić z nich, używając obiektów Mock z pewną uproszczoną odpowiedzią.
źródło