Czytałem przypadki za i przeciw użyciu wzoru singleton. Jeden wspólny przypadek opisuje trudności w testowaniu jednostkowym z pojedynczymi, ale nie jestem pewien, dlaczego tak jest? Jeśli test jednostkowy jest częścią kompilacji, czy nie mógłbyś po prostu odwołać się do singletonu i użyć go, gdy jest potrzebny? (Myślę z perspektywy java, ale chyba nie powinno to mieć znaczenia)Dlaczego testowanie systemu zależnego od singletonów jest trudne?
Odpowiedz
Wspaniały artykuł na ten temat to Singletons are Pathological Liars. Opisuje to, używając prostego przykładu, dlaczego testowanie przy użyciu singletonów jest nieoczekiwanie trudne.
This Google Techtalk radzi sobie całkiem dobrze z opisywaniem problemów z singletonami i stanem globalnym, jeśli chodzi o testowanie jednostkowe.
Nie przypominam sobie, żebym to kiedykolwiek przeczytał, ale podejrzewam, że problem polega na tym, że można utworzyć tylko jeden. W niektórych przypadkach może to nie być problem, po prostu przetestuj go normalnie.
Ale co jeśli chcesz stworzyć i przetestować inny, być może z różnymi parametrami konstruktora/metody fabryki? Czy restartujesz maszynę JVM? Lub utwórz swój singleton tak, aby nie był to singleton i można go zresetować? Niedobrze.
Jeśli odwołasz się do pojedynczej klasy, która istnieje poza testowaną klasą, nie masz już prawdziwego testu jednostkowego. Zamiast testować pojedynczą jednostkę - klasę docelową - testujesz teraz dwie jednostki - docelową klasę i singleton.
Istnieje również fakt, że obiekty singleton mają tendencję do posiadania stanu. Aby testy jednostkowe były powtarzalne, te zmiany stanu muszą zostać wycofane po zakończeniu testu jednostkowego. Alternatywnie, musisz utworzyć fałszywą wersję singletonu, która jest niszczona po uruchomieniu każdego testu. Dodaje sporą ilość narzutów, zarówno w kodzie źródłowym, jak iw czasie działania.
Ponieważ singleton jest zmienną globalną OOPish. Zasadniczo, wszystkie funkcje polegające na użyciu singletonu (bezpośrednio lub pośrednio) nie są gwarantowane jako deterministyczne (tj. Nie można oczekiwać, że funkcja zwróci te same wyjścia dla tych samych wejść T przy każdym uruchomieniu).
Singletons są problemem z kilku powodów:
- Są to szczególny przypadek usługi lokalizatora, który zapewnia mechanizm „daj mi jeden z tych”, które nie zawsze jest łatwe do zastąpienia, gdy potrzebne.
- Udostępniają punkt wejścia do odczytu lub zapisu zmiennych globalnych. Zawinięcie tych globalnych zmiennych w obiekcie za pomocą tylko jednej instancji, która jest globalnie dostępna za pośrednictwem wzorca Singleton, nie powoduje, że przestają być globalnymi zmiennymi.
- Są też kłopoty z konserwacją. Na przykład, co się stanie, gdy przestaną być prawdziwymi Singletonami - może trzeba uzyskać dostęp do dwóch baz danych zamiast "bazy danych"?
TL; DR Ten sam obiekt jest dzielony między wszystkie testy, co może być uciążliwe.
Jeśli singleton ma jakiś stan i przeprowadzasz na nim wiele testów, to kolejność testowania może stać się problemem. Wyobraź sobie singleton "MailStore", który zawiera listę wiadomości. Chcę napisać test jednostkowy do listowania wiadomości, a drugi do ich usunięcia.
Oczywiście, jeśli "lista" zostanie uruchomiona przed "usunięciem", być może jest to w porządku. Jeśli "usuń" działa przed "listą", to walczymy, ponieważ nie ma nic do usunięcia. (Wyniki zmieniają się w zależności od kolejności przeprowadzania testów.)
- 1. Obejście problemu odwrotnego wywołania zależnego od argumentu?
- 2. Łańcuch formatu dla wyjścia zależnego od zmiennej
- 3. Testowanie instalatorów systemu Windows
- 4. Dlaczego klasy typów były trudne do wdrożenia?
- 5. Wystawianie typu zależnego od ścieżki pochodzącego z typu singleton
- 6. Obiekty Scala i powstanie singletonów
- 7. PHP - Trudne obliczenie matematyczne
- 8. Dlaczego Scala nie może wyprowadzić ścieżki typu zależnego od ścieżki, nawet z wyraźnego samoodniesienia?
- 9. Oczekiwanie na wydarzenie w Javie - jak trudne jest to?
- 10. dlaczego Google InfoWindow CSS nie jest ujawniony? Dostosowanie jest zbyt trudne.
- 11. Najlepsze praktyki wtrysku zależnego
- 12. Ograniczenia pisania zależnego w Idrisie
- 13. Utwórz testowanie apk systemu Android przy użyciu systemu gradle build
- 14. Co jest przyczyną zależnego od wymiaru AttributeError w funkcji fromarray PIL?
- 15. Testowanie królestwa pod kontrolą systemu Android
- 16. Dlaczego ciąg.IsNullOrEmpty jest szybszy od porównania?
- 17. Dlaczego PhoneGap jest wolniejszy od przeglądarki?
- 18. Dlaczego jQuery jest zależne od Ember.js?
- 19. Testowanie jednostki HttpInterceptor od Angular 4
- 20. Używanie Injection Dependency jako alternatywy dla Singletonów
- 21. Nie można zdefiniować elementu zależnego typedef
- 22. Testowanie XHR w Jest
- 23. Testowanie systemu a testy akceptacyjne - Różnice w przypadkach testowych
- 24. Czy wstrzyknięcie zależne od narkotyków może być podobne do Typhoon zamiast wielu singletonów?
- 25. Reset Git - trudne i zdalne repozytorium
- 26. Średnie ponad trudne do zdefiniowania partycji
- 27. animacji CSS trudne błąd w Chrome
- 28. Rozwidlenie procesu potomnego i wstrzyknięcia zależnego
- 29. Jak używać wtrysku zależnego od konstruktora do dostarczania modeli z kolekcji do ich modeli ViewModels?
- 30. Jak uruchomić skrypt npm z zależnego pakietu
Link jest uszkodzony. – Emil
Działa dobrze tutaj. –
Świetny artykuł, +1. Jedyną rzeczą, którą chciałbym, żeby ten artykuł się zmienił, jest końcowy przykład ... dla mnie bardziej sensowne jest, aby metoda charge() znajdowała się na karcie CreditCardProcessor i aby była pobierana jako karta i kwota jako parametry :) – rmeador