2010-10-06 6 views
22

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

18

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.

+4

Link jest uszkodzony. – Emil

+2

Działa dobrze tutaj. –

+0

Ś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

2

This Google Techtalk radzi sobie całkiem dobrze z opisywaniem problemów z singletonami i stanem globalnym, jeśli chodzi o testowanie jednostkowe.

-2

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.

5

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.

4

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).

2

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"?
4

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.)

Powiązane problemy