Testowanie serwisów w Spring Boot

0

Hej, mam szybkie pytanie:
do pewnego momentu pisałem testy jednostkowe serwisów używając adnotacji @SpringBootTest co powodowało dość długie odpalanie testów ze względu na podnoszący się cały Springowy context. W tym konkretnym środowisku przydawało mi się to tylko do możliwości używania @Autowired, żeby wstrzyknąć sobie serwisy do klasy testowej. Doszedłem jednak do wniosku, że jest to niepotrzebne i na potrzeby testów mogę pozbyć się @SpringBootTest i każdy z testowanych serwisów przygotować sobie poprzez new. Profit jaki dzięki temu uzyskałem to ogromna oszczędność czasu - bez podnoszenia całego Springa moje suity wypalają się bardzo szybko i zapewnia mi to dużą wygodę. Weryfikowałem poprawność przebiegu testów i nie mam zastrzeżeń. Serwisy są bezstanowe, gdy potrzebuję jednego w drugim robię sobie kaskadowo coś w stylu:

Serwis1 serwis1 = new Serwis1();
Serwis2 serwis2 = new Serwis2(serwis1);

Czy mimo, że to wszystko działa i testuje to co ma testować to jest to jakaś profanacja, czy całkowicie dopuszczalne i eleganckie rozwiązanie? Cała sprawa dzieje się w prywatnym pet projectcie, także nigdzie w świat to nie wyjdzie, ale fajnie być świadomym słuszności swoich decyzji.

3

Imo żadna profanacja, tak się powinno testować jednostkowo. Kontekst springowy zostaw dla długich testów integracyjnych

2
  1. Nie jest to żadna profanacja, to jest zupełnie normalne podejście jeśli chcesz testować implementacje, tzn sprawdzać czy dany kawałek kodu/obiekt/metoda zachowuje sie tak jak powinien.
  2. Pamiętaj tylko, że takie testy wcale nie znaczą że funkcja systemu działa, bo właśnie ominąłeś sporą część aplikacji żeby "dojść" do tego serwisu. Przetestowałes jakąśtam metodę jakiegoś obiektu, ale ta metoda w ogóle może nigdy nie być wywoływana ;) Nie mówiąc o już o takich rzeczach jak jakieś Auth czy CORS. Dlatego ja osobiście sugerowałbym jednak testować jak się zachowuje cały system (czyli wstać aplikacje i stukać do niej klientem) a takie testy kodu zostawić dla konkretnych sytuacji gdzie jest złożona logika którą chcesz dokładniej sprawdzić (np. masz tam jakiś parser). Pamiętaj że generalnie testami chcesz sprawdzać kod jaki faktycznie będzie potem działać na produkcji, a teraz testujesz jak się zachowa new Serwis1(new Serwis2());.
1

Bawiliśmy się tak w jednym projekcie - stawialiśmy cały kontekst (moduł) bez Springa. Ma to swoje duże plusy - jesteś w stanie łatwo podstawić fejki i inne repozytoria in-memory. Trick polega na tym, ze wołasz metodę z @Configuration, która jest odpalana na produkcji - w ten sposób testujesz właściwy kod. Polecam do unit testów na poziomie większych całości/modułów. Oczywiście nie były to jedyne testy, integracyjne tez mieliśmy.

0
Shalom napisał(a):
  1. Nie jest to żadna profanacja, to jest zupełnie normalne podejście jeśli chcesz testować implementacje, tzn sprawdzać czy dany kawałek kodu/obiekt/metoda zachowuje sie tak jak powinien.

O, to super - właśnie do czegoś takiego potrzebne mi są te konkretne testy, o które spytałem. Zdaję sobie sprawę, że do przetestowania jeszcze będzie system w szerszym kontekście, ale przygotuję do tego inną suitę testową.

Shalom napisał(a):
  1. Pamiętaj tylko, że takie testy wcale nie znaczą że funkcja systemu działa, bo właśnie ominąłeś sporą część aplikacji żeby "dojść" do tego serwisu. Przetestowałes jakąśtam metodę jakiegoś obiektu, ale ta metoda w ogóle może nigdy nie być wywoływana ;) Nie mówiąc o już o takich rzeczach jak jakieś Auth czy CORS. Dlatego ja osobiście sugerowałbym jednak testować jak się zachowuje cały system (czyli wstać aplikacje i stukać do niej klientem) a takie testy kodu zostawić dla konkretnych sytuacji gdzie jest złożona logika którą chcesz dokładniej sprawdzić (np. masz tam jakiś parser). Pamiętaj że generalnie testami chcesz sprawdzać kod jaki faktycznie będzie potem działać na produkcji, a teraz testujesz jak się zachowa new Serwis1(new Serwis2());.

W zasadzie trafiłeś w dychę z tymi parserami - dokładnie do czegoś takiego potrzebne mi są te testy. Mam jakieś różne implementacje parserów, formatterów etc., które obsługują trochę inaczej spreparowane dane i te testy pisałem na potrzeby sprawdzenia ich zachowania w przypadku danych prawidłowych, danych niekompletnych, danych popsutych itd. Tego Springa mam tam generalnie tylko po to, żeby procesowane w backendzie dane wyświetlać na froncie i udostepniać endpointy GETowe do oglądania ich. Czemu Spring? Nie znam niczego innego, a i wyklikanie szablonu projektu i autokonfiguracja znacznie ułatwiła mi sprawę i pozwoliła przejść do rozwiązywania clue problemu. A sam backend mógłby się obejść bez Springa, bo korzystam tam tylko z @Service i @Autowired i cały proces transformowania danych odbywa się niezależnie od requestu HTTP. Nie ma sensu wchodzić za bardzo w szczegóły, bo nawet może to nikogo nie interesować, ale zmierzam do tego, że Auth itd po prostu tam nie istnieje. Toteż cięższe testy z kontekstem Springowym zostawiłbym sobie do przetestowania bardzo ograniczonej liczby możliwości interakcji użytkownika z systemem. Nie łączę się też z żadną bazą danych (chociaż może w przyszłości dojdzie tam taka funkcjonalność i wtedy wzrośnie liczba testów @SpringBootowych.

Chyba wszyscy mnie utwierdziliście w przekonaniu, że to rozwiązanie jest spoko. W międzyczasie znalazłem też kilka wypowiedzi na SO, których autorzy również zalecali ograniczenie stawiania kontekstu springa do testów, gdzie ten kontekst coś wnosi. Zatem zostawiam istniejące testy tak jak są i biorę się za pokrywanie reszty kodu. Dzięki wielkie wam za szybkie odpowiedzi! :)

1

Tego kontekstu Springa tez nie ma co demonizować, bo on jest podnoszony tylko raz (chyba, że używasz @DirtiesContext lub @MockBean)

1

@Charles_Ray: Nie demonizuję, ale zabierało mi to czas, gdy chciałem wypalić selektywnie jeden test, czy nawet jakieś 2-3 unity, żeby coś sprawdzić, a czekałem znacznie dłużej niż teraz. Często przez to olewałem testy, przy jakichś zmianach komentowałem te, które nie przechodziły, bo nie chciało mi się aż tak ich poprawiać.
Nie chcę się pozbywać konktekstu Springa, bo go nie lubię, tylko bo mi się nie chce czekać kilkunastu sekund na wynik jednego testu :D

1 użytkowników online, w tym zalogowanych: 0, gości: 1