Próbuję przetestować klasę, która wywołuje niektóre usługi sieciowe Hadoop. Kod ma prawie postać:
method() {
...use Jersey client to create WebResource...
...make request...
...do something with response...
}
np. istnieje metoda tworzenia katalogów, metoda tworzenia folderów itp.
Biorąc pod uwagę, że kod dotyczy zewnętrznej usługi internetowej, nad którą nie mam kontroli, jak mogę to przetestować? Mógłbym próbować kpić z klienta / odpowiedzi usługi sieci Web, ale to łamie wskazówkę, którą ostatnio często widziałem: „Nie kpij z obiektów, których nie posiadasz”. Mógłbym skonfigurować fałszywe wdrożenie usługi internetowej - czy nadal stanowiłoby to „test jednostkowy”, czy też byłby to test integracji? Czy po prostu nie jest możliwe przeprowadzenie testu jednostkowego na tak niskim poziomie - jak by to zrobił specjalista TDD?
unit-testing
tdd
web-services
integration-tests
Chris Cooper
źródło
źródło
Odpowiedzi:
Moim zdaniem powinieneś wyśmiewać wywołania usługi internetowej, jeśli jest to test jednostkowy, a nie test integracyjny.
Twój test jednostkowy nie powinien sprawdzać, czy zewnętrzna usługa internetowa działa lub czy twoja integracja z nią jest prawidłowa. Nie przesadzając z dogmatycznym podejściem do TDD, zauważ, że efektem ubocznym przekształcenia testu jednostkowego w test integracyjny jest to, że może on działać wolniej i potrzebujesz szybkich testów jednostkowych.
Ponadto, jeśli usługa tymczasowo nie działa lub działa nieprawidłowo, czy powinno to spowodować niepowodzenie testu urządzenia? To nie wydaje się właściwe. Twój test jednostkowy powinien zakończyć się niepowodzeniem tylko z jednego powodu: jeśli w kodzie w tej „jednostce” występuje błąd.
Jedyną istotną częścią kodu jest tutaj
...do something with response...
. Kpij z reszty.źródło
Nie zgadzam się z „nie kpij sobie z obiektów, których nie posiadasz”, gdy przeprowadzasz testy jednostkowe.
Pozornym celem istnienia jest fakt, że będą moduły, biblioteki, klasy, których nie będziemy posiadać.
Moją propozycją dla twojego scenariusza jest udawanie połączenia z serwisem internetowym.
Skonfiguruj próbkę w taki sposób, aby zwracała dane z powrotem do modułu.
Upewnij się, że uwzględniono wszystkie scenariusze, np. Gdy zwracane dane są zerowe, gdy zwracane dane są prawidłowe itp.
W przypadku kodu, który posiadasz, Twoim obowiązkiem jako programisty jest upewnienie się, że kod, który tworzysz, działa zgodnie z oczekiwaniami we wszystkich scenariuszach.
źródło
Do tego testu użyłbym czegoś takiego jak EasyMock. Frameworki są idealnym sposobem na usunięcie zewnętrznych zależności od klasy i dają całkowitą kontrolę nad wynikiem zależności zewnętrznych podczas testów. Aby nieco rozszerzyć swój przykład:
Pierwszą rzeczą, którą musisz zrobić, to wyodrębnić logikę w swojej klasie, w której używasz Jersey, aby uzyskać WebResource i wywołać usługę internetową do osobnej klasy. Utworzenie interfejsu dla tej klasy pozwoli ci stworzyć próbkę, do której możesz następnie dyktować zachowanie.
Po utworzeniu tego interfejsu można utworzyć próbkę za pomocą EasyMock, która zwróci określony obiekt zgodny z przypadkiem testowym. Powyższy przykład stanowi uproszczenie struktury podstawowego próbnego testu i działania interfejsu.
Aby uzyskać więcej informacji na temat ramek próbnych, zobacz to pytanie . Ponadto w tym przykładzie założono użycie Java, ale frameworki są dostępne we wszystkich językach i chociaż są zaimplementowane inaczej, będą działać w ten sam sposób
źródło
W tym przypadku możliwe są symulacje, ale nie są one potrzebne. Zamiast testowania jednostkowego
method()
, zamiast testowania jednostkowego tylko część, która obsługuje odpowiedź.Wyodrębnij funkcję, która bierze
ResponseData
(dowolnego rodzaju), a następnie wykonuje akcję.Zamiast kpić, teraz konstruujesz obiekt ResponseData i przekazujesz go.
Możesz pozostawić wezwanie usługi do pełnego testu integracji - który obejmie
method()
w całościźródło
Co zrobiłem i działa:
3.1 Najpierw testowane są wszystkie usługi sieciowe. Z każdej maszyny, nawet maszyny programisty. To są prawdziwe usługi internetowe, ale działają w środowisku programistycznym. Oznacza to, że usługi internetowe nigdy nie mogą być wyłączone lub odpowiadać na błędne wartości, ponieważ w przeciwnym razie każdy programista narzeka, że nie może się skompilować.
3.2 Następnie uruchamiane są wszystkie testy jednostkowe wewnętrzne aplikacji. Oznacza to, że wszystkie usługi internetowe są wyśmiewane i testowane, uruchamiając te same testy co 3.1 (anbde powinny one również przejść, w przeciwnym razie wyśmiewane są błędne) i wywoływane przez prawdziwą aplikację tak, jakby były rzeczywiście używane. Jeśli próby są nieprawidłowe, możesz uruchomić test w wersji 3.1 i zapisać te wartości (żądanie, odpowiedź) w HashMap.
3.3 Następnie uruchamiane są te same testy co 3.2, ale tym razem z prawdziwymi usługami internetowymi działającymi w środowisku programistycznym.
Po wykonaniu wszystkich tych czynności w prawdziwym środowisku produkcyjnym wystarczy podać prawdziwy adres dla każdej usługi sieciowej. Mamy nadzieję, że nie wymaga to zbyt dużej zmiany w konfiguracji.
źródło