Lekcja 1.6: Testy jednostkowe

Testy jednostkowe


Na koniec modułu wprowadzającego spróbujemy dopisać testy jednostkowe, żeby pokazać, że użycie wstrzykiwania zależności czy też programowania aspektowego ułatwia testowanie. Żeby pokazać, że również na tym polu bardzo dużo zyskujemy. Wykorzystamy bardzo popularne biblioteki. To jest junit i mockito. Zaczniemy od zdefiniowania ich w wersji na poziomie properties. Następnie dodamy zależności. Aby testy mogły być uruchamiane z poziomu Mavena, powinniśmy dodać także odpowiedni plugin. Na tym etapie jesteśmy gotowi do tego, żeby napisać pierwszy test. Możemy zatem otworzyć katalog test/java i dodać tam odpowiednią strukturę pakietów. Zacznijmy od przetestowania naszych generatorów. Czyli możemy utworzyć klasę UUIDPaymentIdGeneratorTest i w ramach takiej klasy możemy stworzyć pierwszy bardzo prosty test, który będzie odpowiadał na pytanie, czy nasz wygenerowany identyfikator jest zgodny z bieżącą implementacją, jest po prostu właściwy. Taka metoda powinna być oczywiście oznaczona adnotacją @Test. Możemy dodatkowo umieścić tu adnotację @DisplayName. Tekst, który definiujemy, będzie wyświetlany w ramach podsumowania testu, dzięki czemu wyniki testów będą dużo bardziej czytelne. I pozostaje nam ta właściwa część testu. Na pewno potrzebujemy generatora, który będziemy testowali. Potrzebujemy też czegoś, co będzie określało wzór, wzorzec poprawnego identyfikatora. Spróbujemy wykorzystać tu wyrażenie regularne, które opisuje identyfikator UUID. Czyli powiemy, że będziemy mieli najpierw osiem znaków alfanumerycznych, myślnik, następnie cztery znaki alfanumeryczne, dalej znowu cztery znaki alfanumeryczne, i kolejne cztery. A na zakończenie jeszcze dwanaście. Teraz możemy wygenerować nowe id sprawdzić, czy jest ono zgodne z zakładanym formatem. Nasz pierwszy prosty test jest gotowy. Możemy spróbować go uruchomić i zobaczyć czy wszystko jest w porządku. Jak widać, nasz test przeszedł pomyślnie. Możemy zatem spróbować zaimplementować kolejne testy pod kątem drugiego generatora. Zaczniemy od zdefiniowania poprawnego formatu identyfikatora pod kątem tego generatora. Tym razem będzie to dokładnie dziesięć cyfr. Potrzebujemy także instancji samego generatora. Nasz pierwszy test będzie wyglądał identycznie jak ostatnio, w związku z tym możemy się pokusić o jego skopiowanie. Natomiast z pewnością możemy tu dodać jeszcze jeden test, który będzie weryfikował to, czy kolejne generowane identyfikatory faktycznie powstają poprzez inkrementację poprzedniej wartości. Pozostaje nam wygenerować dwie wartości i zweryfikować czy kolejna powstała poprzez zwiększenie poprzedniej. Brakuje nam jeszcze adnotacji @Test i możemy spróbować wykonać oba testy. W obu przypadkach mamy sukces. Mamy informację zwrotną o tym, że nasz generator powinien działać prawidłowo. Ostatnią klasą, którą spróbujemy przetestować na tym etapie, będzie FakePaymentService. Tym razem testy będą odrobinę trudniejsze, dlatego że będziemy musieli zaślepić zależności, z którymi będziemy współdziałali. Zgodnie z założeniem, klasy testowane jednostkowo powinny być odizolowane od swoich zależności. Dodajmy zatem FakePaymentServiceTest. Wykorzystamy tu rozszerzenie pozwalające na to, żeby obiekty mock były generowane za pomocą adnotacji. Na początek potrzebujemy kilku parametrów konfiguracyjnych np. identyfikatora płatności. Potrzebujemy także przykładowej kwoty, na której będziemy operowali. Na podstawie samej kwoty tworzymy teraz żądanie płatności. Teraz możemy przejść do zdefiniowania naszych zależności. Zależnością w przypadku FakePaymentService jest PaymentIdGenerator. Użyjemy mockito aby stworzyć dublera, obiekt zastępczy, który będzie udawał prawdziwy generator. Teraz tego stworzonego dublera spróbujemy nauczyć jak ma się zachowywać, tak żeby to odpowiadało naszym wymaganiom testowym, czyli powiemy, że jeżeli ktoś zapyta go o kolejny numer, kolejny identyfikator dla płatności to my chcemy po prostu, żeby on zwrócił nasze PaymentId. Tworzymy metodę setUp. Oznaczamy tę metodę adnotacją @BeforeEach. To spowoduje że będzie ona wołana przed każdym testem w naszej klasie. I teraz powiemy, że jeżeli ktoś zawoła metodę getNext na poziomie naszego generatora, to my chcemy zwrócić Payment id. Dodatkowo oczywiście musimy też utworzyć instancję tej klasy, którą będziemy testowali. W ramach konstruktora podamy nasz obiekt zastępczy, czyli PaymentIdGenerator. Na koniec spróbujemy jeszcze przeprocesować PaymentRequest tak, żeby otrzymać obiekt płatności, który będziemy za chwilę weryfikowali. Mamy już wszystko, co jest potrzebne do tego, żeby pisać teksty. One dzięki temu, że wyodrębniliśmy ten wspólny kod do metody setUp będą bardzo proste i czytelne. Pierwsza kwestia, którą powinniśmy zweryfikować to to, czy taki generowany identyfikator jest przypisywany do naszej płatności, kiedy ją procesujemy. Czyli spróbujmy napisać taki test. Sam test będzie bardzo prosty, bo będzie to po prostu kwestia porównania naszego skonfigurowanego PaymentId z tym co otrzymaliśmy na poziomie Payment. Kolejny test może weryfikować czy kwota, którą przekazaliśmy w ramach żądania, została także ustawiona na poziomie Payment. Możemy zweryfikować czy w ramach płatności został przypisany znacznik czasowy, czasowy, czy jest on po prostu różny od null. I ostatni test – powinniśmy zweryfikować czy nasza płatność ma status ustawiony na STARTED. Możemy teraz spróbować uruchomić testy. Wszystkie testy zostały wykonane poprawnie. Widać, że stworzenie tych testów mimo tego, że występowały zależności pomiędzy generatorem i usługą realizującą płatności, wcale nie było trudne. Jest to bardzo prosty przykład, ale w dużej mierze pokazuje, to co się będzie działo w większej aplikacji. Także podsumowując widać, że te fundamenty, na których zbudowany jest Spring pozwalają na to, żeby faktycznie budować kod, który będzie dużo bardziej jakościowy, ale też, który będzie dużo łatwiejszy w utrzymaniu w dłuższej perspektywie czasowej.

Zaloguj się
Rejestracja jest darmowa!

Administratorem danych jest Sages Sp. z o.o. z siedzibą w Warszawie przy ul. Nowogrodzkiej 62c. Podanie danych jest dobrowolne. Osobie, której dane dotyczą przysługuje prawo wglądu do danych osobowych, ich zmiany oraz usunięcia w sposób określony w Polityce prywatności.

Please accept the Terms and Conditions to proceed.