Różne instancje Singletona z testami JUnit

Mam samodzielny singleton, który pomyślnie przechodzi test. Ale w przypadku grupy testów to się nie powiedzie, ponieważ po zdefiniowaniu Singletona nie pozwala na resetowanie instancji.

Jakieś pomysły jak to zrobić?

Author: kal, 2010-01-30

7 answers

Nie używaj Singletona.

W szczególności, jedyną różnicą między zmienną singleton a zmienną globalną jest to, że singleton próbuje wymusić pojedynczą instancję (na przykład przez uczynienie konstruktora prywatnym).

Zamiast tego upublicznij konstruktor i napisz testy używając nowych instancji. W twoim programie użyj getInstance(), Aby uzyskać globalną instancję canonical (lub użyj kontenera IOC).

I pamiętaj, że singletony są patologicznymi kłamcami.

Jeśli zamiast publikować konstruktor, możesz dodać publiczną (i statyczną) metodę fabryczną, aby tworzyć instancje w sposób, który nie może być użyty przez przypadek, np.:

public static MyClass TEST_CreateInstance() {
  return new MyClass();
}
 10
Author: orip,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-02-01 21:09:25

Zakładam, że masz prywatne statyczne pole w klasie singleton do przechowywania zainicjowanej instancji.

Jeśli nie chcesz modyfikować kodu, możesz zdefiniować metodę teardown, która będzie uruchamiana po każdym teście i w tej metodzie ustawisz to statyczne pole NA null poprzez odbicie, jak pokazano tutaj .

 10
Author: Csaba_H,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:26:29

Możesz dodać metodę zniszczenia Singletona, na przykład destroyMe (); gdzie wszystko deinicjalizujesz i ustawiasz instancję Singletona NA null.

  public void destroyMe(){
   this.instance = null;
   //-- other stuff to turn it off.
}

Zostawię jednak problemy z synchronizacją;)

Ale dlaczego musisz ponownie inicjować swój singleton dla każdego testu? Nie powinno się różnić w oparciu o koncepcję Singletona.

 3
Author: Omar Al Kababji,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-05-15 17:49:17

I gorąco zalecam odejście od singletonów jako wzorca projektowego i użycie Singletona jako zakresu (iniekcji zależności). To po prostu sprawi, że twój problem zniknie.

Ale zakładając, że utknąłeś w świecie singletonów, masz kilka opcji w zależności od tego, Czy testujesz Singleton, czy zależność.

Jeśli testujesz element zależny, możesz wyśmiewać Singleton używając PowerMocki JMockIt. Zobacz mój poprzedni post o wyśmiewaniu Runtime.getRuntime dla instrukcji, Jak to zrobić.

Jeśli testujesz Singleton, musisz rozluźnić zasady budowy lub dać Singletonowi metodę "Reset".

 2
Author: Michael Lloyd Lee mlk,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 10:29:41

Generalnie uważaj na singletony, najczęściej są one złe, złe i mają tendencję do reprezentowania dużych zmiennych globalnych (co jest złe dla utrzymania).

Jeszcze żeby najpierw zrobić testy możesz zrobić:


static setInstance(...){ //package visibility or in difficult cases you have to use public
  instance = ...;
}

Jak powiedział, Jest to bardziej obejście. więc zdobądź pierwsze miejsce testów, ale potem refaktor z dala od wzoru Singletona.

 1
Author: manuel aldana,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-01-30 07:55:27

Spring zapewnia adnotację DirtiesContext dla tego konkretnego przypadku użycia, w którym potrzebujesz nowych wystąpień ziaren Singletona dla każdej skrzynki testowej. Zasadniczo tworzy nowy kontekst aplikacji dla każdej skrzynki testowej / klasy testowej, w której zastosowano tę adnotację.

 1
Author: Andy Dufresne,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-03-18 08:25:17

Instancja Singletona musi zostać przekazana do SUT przez sam test - w ten sposób tworzysz singleton (i niszczysz) dla każdego testu. Przyjęcie IoC I wyśmiewanie RAM, jak Mockito, uczyniłoby to podejście niemal banalnym.

 0
Author: topchef,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-02-01 20:58:47