Dev Foundry http://devfoundry.pl programowanie • java • spring • kursy Thu, 05 Dec 2019 09:11:44 +0000 pl-PL hourly 1 https://wordpress.org/?v=5.0.10 http://devfoundry.pl/wp-content/uploads/2018/05/cropped-DEVfoundry_SYMBOL_512x512-32x32.png Dev Foundry http://devfoundry.pl 32 32 Santa Cloud – więcej niż meetup IT! http://devfoundry.pl/santa-cloud-wiecej-niz-meetup-it/ http://devfoundry.pl/santa-cloud-wiecej-niz-meetup-it/#respond Thu, 05 Dec 2019 08:59:40 +0000 http://devfoundry.pl/?p=1221 Jest nam bardzo miło poinformować, że jesteśmy partnerami katowickiego meetupu IT – Santa Cloud! Ale Santa Cloud to coś więcej niż zwykły meetup IT! Po raz piąty spotykamy się, aby wysłuchać inspirujących prelekcji i pomóc zwierzętom! W tym roku widzimy się 10 grudnia o 18:00 w Restauracji Królestwo w Katowicach. W programie blok prezentacji, występ magika, aukcja charytatywna i networking! Czekają na Was: Piotr Łój – Czy VR może wyrównywać szanse dla grup wykluczonych?” Gosia Bekas – “A gdyby Twój pies ...

Czytaj dalej...Santa Cloud – więcej niż meetup IT!

The post Santa Cloud – więcej niż meetup IT! appeared first on Dev Foundry.

]]>
Jest nam bardzo miło poinformować, że jesteśmy partnerami katowickiego meetupu IT – Santa Cloud!

santa cloud meetup it
santa cloud meetup it

Ale Santa Cloud to coś więcej niż zwykły meetup IT! Po raz piąty spotykamy się, aby wysłuchać inspirujących prelekcji i pomóc zwierzętom! W tym roku widzimy się 10 grudnia o 18:00 w
Restauracji Królestwo w Katowicach.

W programie blok prezentacji, występ magika, aukcja charytatywna i networking! Czekają na Was:

  • Piotr Łój – Czy VR może wyrównywać szanse dla grup wykluczonych?”
  • Gosia Bekas – “A gdyby Twój pies sam mógł umówić się do weta”

Oraz trzeci tajemniczy prelegent, który zostanie ogłoszony niebawem 🙂

To wszystko? Skąd! W przerwie czeka na Was występ magika, a po prezentacjach – niczym wisienka na torcie – aukcja charytatywna “Giełda marzeń”, podczas której wylicytujecie “fanty”, które wzbogacą Wasze życie zawodowe (np. voucher na kurs programowania, konsultacja jak pozyskiwać fundusze od VC, biznesowa sesja zdjęciowa…) — i prywatne (np. nauka bachaty, czy warsztaty z improwizacji)!

A od Dev Foundry na aukcję trafią zestawy voucherów na darmowy dostęp do wszystkich naszych kursów!

Do zobaczenia na Santa Cloud!

Więcej informacji: https://www.facebook.com/events/674375663054513

The post Santa Cloud – więcej niż meetup IT! appeared first on Dev Foundry.

]]>
http://devfoundry.pl/santa-cloud-wiecej-niz-meetup-it/feed/ 0
Różnice pomiędzy final, finally, a finalize http://devfoundry.pl/roznice-pomiedzy-final-finally-a-finalize/ http://devfoundry.pl/roznice-pomiedzy-final-finally-a-finalize/#respond Tue, 05 Nov 2019 09:04:03 +0000 http://devfoundry.pl/?p=1206 Jednym z pytań pojawiających się podczas rozmowy kwalifikacyjnej na pozycje młodszego programisty jest to, o różnice pomiędzy działaniami słów kluczowych final i finally oraz metody finalize. Funkcjonalności te, wbrew pozorom, poza zbliżonymi nazwami nie mają ze sobą nic wspólnego. Na poniższym filmie omawiam działanie każdego z nich:   Final jest słowem kluczowym, które użyte ze zmienną zamienia ją w stałą. Natomiast użyte wraz z metodą powoduje, iż nie można jej nadpisać. Można również wykorzystać je wraz z klasą – wówczas ...

Czytaj dalej...Różnice pomiędzy final, finally, a finalize

The post Różnice pomiędzy final, finally, a finalize appeared first on Dev Foundry.

]]>
Jednym z pytań pojawiających się podczas rozmowy kwalifikacyjnej na pozycje młodszego programisty jest to, o różnice pomiędzy działaniami słów kluczowych final i finally oraz metody finalize. Funkcjonalności te, wbrew pozorom, poza zbliżonymi nazwami nie mają ze sobą nic wspólnego.

Na poniższym filmie omawiam działanie każdego z nich:

 

Final jest słowem kluczowym, które użyte ze zmienną zamienia ją w stałą. Natomiast użyte wraz z metodą powoduje, iż nie można jej nadpisać. Można również wykorzystać je wraz z klasą – wówczas blokuje ono możliwość dziedziczenia danej klasy.

Finally jest elementem bloku try-catch-finally. Operacje zawarte w tej sekcji zostaną zawsze wykonane – niezależnie czy kod zawarty w sekcji catch zakończył się sukcesem, czy rzucił wyjątkiem.

Finallize jest natomiast metodą z klasy Object, która w teorii miała być wywoływana przed tym, gdy dany obiekt zostanie usunięty z pamięci. W praktyce nie zawsze (albo wręcz z reguły) nie działała w 100%. Obecnie oznaczona jest jako deprecated i nie powinna być używana pod żadnym pozorem.

Jeśli ten post Ci się przydał podziel się nim proszę w swoich social mediach 🙂

The post Różnice pomiędzy final, finally, a finalize appeared first on Dev Foundry.

]]>
http://devfoundry.pl/roznice-pomiedzy-final-finally-a-finalize/feed/ 0
Modyfikatory dostępu w języku Java http://devfoundry.pl/modyfikatory-dostepu-w-jezyku-java/ http://devfoundry.pl/modyfikatory-dostepu-w-jezyku-java/#respond Mon, 07 Oct 2019 13:40:10 +0000 http://devfoundry.pl/?p=1190 Jednym z częstych pytań dla osób starających się o pozycję junior java developera jest pytanie o modyfikatory dostępu, jakie są dostępne w języku Java oraz jak zachowuję się domyślny z nich. W języku Java istnieją cztery modyfikatory dostępu (zwane również modyfikatorami widoczności). Każdy z nich określa czy dana klasa, metodą bądź pole klasy jest widoczne dla innych klas. W języku Java istnieją cztery poziomy, zaczynając od najszerszego są to – public, protected, default (package), private. Trzeba pamiętać, że choć modyfikatory ...

Czytaj dalej...Modyfikatory dostępu w języku Java

The post Modyfikatory dostępu w języku Java appeared first on Dev Foundry.

]]>
Jednym z częstych pytań dla osób starających się o pozycję junior java developera jest pytanie o modyfikatory dostępu, jakie są dostępne w języku Java oraz jak zachowuję się domyślny z nich.

W języku Java istnieją cztery modyfikatory dostępu (zwane również modyfikatorami widoczności). Każdy z nich określa czy dana klasa, metodą bądź pole klasy jest widoczne dla innych klas. W języku Java istnieją cztery poziomy, zaczynając od najszerszego są to – public, protected, default (package), private. Trzeba pamiętać, że choć modyfikatory dostępu są cztery to słów kluczowych je określających jest już tylko trzy – private, public i protected. Poziom package jest poziomem domyślnym i jeśli chcemy go użyć to po prostu nie dodajemy żadnego modyfikatora dostępu przed nazwą pola czy metody.

W filmie poniżej znajdziesz opis na praktycznym przykładzie, zapraszam do obejrzenia.

Public jest najszerszym poziomem widoczności – klasy, pola i metody oznaczone w ten sposób są widoczne dla wszystkich innych klas.

Drugi w kolejności – protected– jest dostępny dla klas zdefiniowanej w tej samej paczce oraz w klasach dziedziczących (extends) po klasie, która zawiera pola czy metody oznaczone jako protected.

Package, będący domyślnym poziomem widoczności nieposiadającym własnego modyfikatora, ogranicza widoczność do klas z tej samej paczki.

Finalnie mamy private– czyli prywatne. Jak sama nazwa wskazuje elementy z dostępem na poziomie prywatnym są widoczne tylko dla struktur zdefiniowanych w tej samej klasie.

Jeśli dowiedziałeś się dzięki temu wpisowi czegoś nowego, będzie nam niezmiernie miło, gdybyś podzielił się tym postem w swoich social mediach.

The post Modyfikatory dostępu w języku Java appeared first on Dev Foundry.

]]>
http://devfoundry.pl/modyfikatory-dostepu-w-jezyku-java/feed/ 0
Wzorzec projektowy Fasada http://devfoundry.pl/wzorzec-projektowy-fasada/ http://devfoundry.pl/wzorzec-projektowy-fasada/#respond Sat, 24 Aug 2019 09:28:42 +0000 http://devfoundry.pl/?p=1173 Fasada jest jednym ze wzorców strukturalnych. Na pierwszy rzut oka może wydawać się podobna do wzorca Adapter, jednak różni je przeznaczenie. Celem wzorca Adapter jest modyfikacja danego interfejsu tak, aby dostosować go do potrzeb klienta. Natomiast celem Fasady jest zapewnienie klientowi uproszczonego interfejsu dla danego systemu lub jego podsystemów. Najczęstszym zadaniem Fasady jest zatem izolacja klienta od podsystemu, czyli wewnętrznych metod oraz logiki biznesowej. Jeśli więc klient ma nie mieć bezpośredniego dostępu do systemu lub podsystemów ze względu bezpieczeństwa, to ...

Czytaj dalej...Wzorzec projektowy Fasada

The post Wzorzec projektowy Fasada appeared first on Dev Foundry.

]]>
Fasada jest jednym ze wzorców strukturalnych. Na pierwszy rzut oka może wydawać się podobna do wzorca Adapter, jednak różni je przeznaczenie. Celem wzorca Adapter jest modyfikacja danego interfejsu tak, aby dostosować go do potrzeb klienta. Natomiast celem Fasady jest zapewnienie klientowi uproszczonego interfejsu dla danego systemu lub jego podsystemów.

Najczęstszym zadaniem Fasady jest zatem izolacja klienta od podsystemu, czyli wewnętrznych metod oraz logiki biznesowej.

Jeśli więc klient ma nie mieć bezpośredniego dostępu do systemu lub podsystemów ze względu bezpieczeństwa, to wzorzec Fasada nadaje się do tego idealnie.

Po więcej szczegółów, zapraszamy do filmu poniżej. Dowiesz się w nim między innymi:

  • jakie są zalety i wady Fasady,
  • poznasz schemat działania Fasady,
  • zobaczysz przykład negatywny,
  • poznasz poprawną implementację wzorca Fasada.

 

Można powiedzieć, że Fasada jest jak interfejs użytkownika: dostępne i widoczne są wybrane funkcjonalności. Użytkownik nie musi znać ani widzieć dokładnie działania systemu wewnętrznego, ponieważ potrzebne funkcjonalności są mu udostępniane na zewnątrz.

Uwaga: jeśli naszym celem nie jest zapewnienie bezpieczeństwa, a jedynie zapewnienie uproszczonego interfejsu dla klienta, to nic nie stoi na przeszkodzie, aby klient nadal miał dostęp do danych klas i metod z podsystemu.

Jest to dość prosty wzorzec i na pewno warto z niego skorzystać, zwłaszcza tam, gdzie potrzebujemy schować pewną część naszego kodu przed klientem lub też jeśli chcemy dostarczyć klientowi uproszczoną wersję danej funkcjonalności.

Jakie są zalety Fasady?

Fasada rozdziela klienta od podsystemów danego systemu. Więc może zapewniać bezpieczeństwo, bo klient nie ma bezpośredniego dostępu do metod podsystemu.

Klient jest oddzielony od niepotrzebnej dla niego wiedzy złożoności działania danego podsystemu.

Natomiast co do wad:

Trzeba pamiętać, że utworzona przez nas fasada jest zależna od klas podsystemów. Jeśli ich działanie ulegnie zmianie, to musimy również aktualizować fasadę. W przeciwnym razie jej działanie będzie nieprawidłowe.

The post Wzorzec projektowy Fasada appeared first on Dev Foundry.

]]>
http://devfoundry.pl/wzorzec-projektowy-fasada/feed/ 0
Testy jednostkowe – Mocki http://devfoundry.pl/testy-jednostkowe-mocki/ http://devfoundry.pl/testy-jednostkowe-mocki/#comments Wed, 10 Jul 2019 07:10:53 +0000 http://devfoundry.pl/?p=1121 Mocki to obiekty, które imitują zachowanie prawdziwych obiektów i prawdziwego kodu. Zadaniem programisty jest zaprogramowanie odpowiedniego działania mocka. Ten wpis jest drugą częścią miniserii o stubach oraz mockach. Poznamy w nim zalety mocków, a także ich ogólną charakterystykę i zastosowanie. Pod tym adresem znajdziesz część pierwszą, w której omawiane są stuby. Jak mocki, to Mockito Aby w ogóle móc skorzystać z obiektów mockowych, należy dodać do projektu zależność w postaci frameworka Mockito. Najlepiej ściągnąć najnowszą wersję, aktualnie jest to wersja 2.25. ...

Czytaj dalej...Testy jednostkowe – Mocki

The post Testy jednostkowe – Mocki appeared first on Dev Foundry.

]]>
Mocki to obiekty, które imitują zachowanie prawdziwych obiektów i prawdziwego kodu. Zadaniem programisty jest zaprogramowanie odpowiedniego działania mocka.

Ten wpis jest drugą częścią miniserii o stubach oraz mockach. Poznamy w nim zalety mocków, a także ich ogólną charakterystykę i zastosowanie. Pod tym adresem znajdziesz część pierwszą, w której omawiane są stuby.

Jak mocki, to Mockito

Aby w ogóle móc skorzystać z obiektów mockowych, należy dodać do projektu zależność w postaci frameworka Mockito. Najlepiej ściągnąć najnowszą wersję, aktualnie jest to wersja 2.25.

My polecamy skorzystanie z zależności, która jest przystosowana do współpracy z frameworkiem JUnitmockito-junit-jupiter.

Odpowiedni artefakt znajdziemy korzystając na przykład z wyszukiwarki na stronie maven.org lub też bezpośrednio z tego odnośnika. Pod tym adresem znajdziemy gotowy plik *.jar lub też gotowy wpis, który możemy wkleić do pliku konfiguracyjnego Mavena lub Gradla.

Czym są mocki?

Mocki to obiekty, których zadaniem jest symulacja działania normalnych obiektów i kodu. Natomiast zadaniem programisty jest odpowiednie zaprogramowanie działania mocka.

Na przykład: jeżeli metoda zostanie wywołana obiekcie mockowym X, to ma zwrócić wartość Y.

Mocki mogą być tworzone dynamicznie w czasie runtime’u aplikacji i są znacznie bardziej elastyczne w porównaniu do stubów. Zapewniają też znacznie więcej funkcjonalności.


Jeśli chcesz prześledzić zmiany krok po kroku w formie wideo, to zapraszamy na nasz kanał na YouTube.


Jak je tworzyć?

Aby porównać mocki bezpośrednio ze stubami, utworzymy klasę testową AccountServiceTest. Jej zadanie będzie takie samo, jak klasy testowej AccountServiceStubTest, gdzie testowaliśmy metodę z serwisu AccountService. (we wpisie z zeszłego tygodnia dotyczącym stubów)

Możemy więc skopiować cały kod z klasy AccountServiceStubTest. Nasza klasa testowa będzie zatem wyglądała tak:

@Test
void getAllActiveAccounts() {

    //given
    AccountRepository accountRepositoryStub = new AccountRepositoryStub();
    AccountService accountService = new AccountService(accountRepositoryStub);

    //when
    List accountList = accountService.getAllActiveAccounts();

    //then
    assertThat(accountList, hasSize(2));

}

Aby teraz zamienic stuba na obiekt mockowy, możemy skorzystać ze specjalnej metody frameworka Mockitomock. Ta metoda pozwala nam na utworzenie obiektu mockowego z danej klasy. W naszym przykładzie będzie to oczywiście klasa AccountRepository:

AccountRepository accountRepositoryMock = mock(AccountRepository.class);

I takiego mocka możemy teraz przekazać do konstruktora klasy AccountService:

AccountRepository accountRepositoryMock = mock(AccountRepository.class);
AccountService accountService = new AccountService(accountRepositoryMock);

Zatem jak było widać na powyższym przykładzie, w bardzo prosty sposób jesteśmy w stanie zamienić obiekt stubowy na obiekt mockowy.

Jednak jeśli teraz uruchomimy tę metodę testową, to asercja nie zostanie spełniona, a test nie przejdzie. W wyniku zobaczymy, że była oczekiwana wartość 2, a w rzeczywistości zwrócona została wartość 0, a więc pusta lista. Dlaczego?

Miłe mocki

Dzieje się tak dlatego, że w Mockito wykorzystywane są tak zwane „nice mocki„. Działają one w specyficzny sposób. Załóżmy, że mamy taką sytuację: w klasie, którą mockujemy znajdują się metody, które zwracają jakieś wartości. Wtedy domyślnie Mockito przy wywołaniu takich metod postara się zwrócić jakieś sensowne wartości, a nie na przykład po prostu  wartość null.

W naszym przykładzie, gdzie zwracana jest lista obiektów typu Account, Mockito zwraca pustą listę. A jeśli metoda miałaby zwracać wartości Integer, to Mockito zwróciłoby wartość 0. Jeśli metoda zwracałaby wartość boolean, to Mockito zwróciłoby wartość false. Więcej informacji można znaleźć w dokumentacji Mockito

W taki sposób będą zachowywały się mocki, jeśli nie zaprogramujemy dla nich żadnego działania. Ale właśnie… przecież możemy to zachowanie zaprogramować!

Szybko, łatwo i przyjemnie

Najpierw musimy przygotować listę danych testowych. Na szczęście mamy już taki zestaw w naszej klasie stubowej, znanej z poprzedniego wpisu. A żeby nie zaśmiecać naszej metody testowej, to dodatkowo ten kod umieścimy w metodzie pomocniczej:

private List prepareAccountData() {
    Address address1 = new Address("Kwiatowa", "33/5");
    Account account1 = new Account(address1);

    Account account2 = new Account();

    Address address2 = new Address("Piekarska", "12b");
    Account account3 = new Account(address2);

    return Arrays.asList(account1, account2, account3);
}

Dla przypomnienia, klasa Account ma postać:

class Account {

    private boolean active;
    private Address defaultDeliveryAddress;

    Account() {
        this.active = false;
    }

    Account(Address defaultDeliveryAddress) {
        this.defaultDeliveryAddress = defaultDeliveryAddress;
        if(defaultDeliveryAddress != null) {
            activate();
        } else {
            this.active = false;
        }
    }

    void activate() {
        this.active = true;
    }

    boolean isActive() {
        return this.active;
    }

    Address getDefaultDeliveryAddress() {
        return defaultDeliveryAddress;
    }

    void setDefaultDeliveryAddress(Address defaultDeliveryAddress) {
        this.defaultDeliveryAddress = defaultDeliveryAddress;
    }

}

Jeśli przy tworzeniu obiektu typu Account skorzystamy z konstruktora bezargumentowego lub też w konstruktorze oczekującym obiektu typu Address przekażemy wartość null, to wtedy utworzone konto będzie nieaktywne, a więc metoda isActive będzie zwracała wartość false. W przeciwnym razie oczywiście zwrócona będzie wartość true.

W naszym przykładzie utworzone zostały 3 konta: account1, account2 i account3. account2 zostało utworzone korzystając z konstruktora bezargumentowego, więc to konto będzie nieaktywne. account1 i accoun3 natomiast będą aktywne.

Możemy teraz wrócić do naszej metody testowej: getAllActiveAccounts . Tutaj chcielibyśmy móc zaprogramować takie działanie:

Jeżeli na mocku zostanie wywołana metoda getAllAccounts , to w wyniku powinna być zwrócona lista kont z metody prepareAccountData.

Aby to zrobić, korzystamy ze specjalnych metod pomocniczych z biblioteki Mockito: when oraz thenReturn:

when(accountRepository.getAllAccounts()).thenReturn(accounts);

Taka składnia jest popularna, ale może być dla kogoś myląca, bo mamy tu kombinację słów when i then, dość podobne do samych sekcji //given, //when i //then.

Zatem żeby zachować ducha Behaviour Driven Development (BDD), można skorzystać z innej kombinacji metod: given i willReturn.

Po zmianach cała metoda testowa prezentuje się następująco:

@Test
void getAllActiveAccounts() {

    //given
    List accounts = prepareAccountData();
    AccountRepository accountRepository = mock(AccountRepository.class);
    AccountService accountService = new AccountService(accountRepository);
    given(accountRepository.getAllAccounts()).willReturn(accounts);

    //when
    List accountList = accountService.getAllActiveAccounts();

    //then
    assertThat(accountList, hasSize(2));

}

I teraz gdy uruchomimy testy, czeka nas miły widok:

stuby mocki testy jednostkowe junit mockito dev foundry blog programowanie java spring kursy

Elastyczność

Powyższy przykład już jasno pokazuje, że mocki są znacznym ułatwieniem względem stubów. Chociażby dlatego, że nie musimy tworzyć osobnej klasy stubowej. Ale jeszcze większą zaletą jest to, jak łatwo możemy tworzyć kolejne scenariusze testowe.

Załóżmy, że chcielibyśmy przetestować sytuację, w której z bazy danych nie zwrócone zostaną żadne konta.

Zatem do klasy testowej dopisujemy kolejną metodę. Nazwiemy ją getNoActiveAccounts.

Część główną metody możemy dla ułatwienia skopiować z metody getAllActiveAccounts. Dodatkowo musimy tutaj dokonać zmiany logicznej. Oczekujemy, że lista kont, którą otrzymamy z bazy danych, będzie pusta. Zmieniamy zatem asercję z:

assertThat(accountList, hasSize(2));

na:

assertThat(accountList, hasSize(0));

I modyfikujemy zawartość metody thenReturn tak, aby obiekt mockowy faktycznie zwracał nam pustą listę (można tu skorzystać na przykład z utilsowej metody Javowej):

given(accountRepository.getAllAccounts()).willReturn(Collections.emptyList());

Ostatecznie cała metoda testowa wygląda tak:

@Test
void getNoActiveAccounts() {

    //given
    AccountRepository accountRepository = mock(AccountRepository.class);
    AccountService accountService = new AccountService(accountRepository);
    given(accountRepository.getAllAccounts()).willReturn(Collections.emptyList());

    //when
    List accountList = accountService.getAllActiveAccounts();

    //then
    assertThat(accountList, hasSize(0));

}

Możemy teraz ją uruchomić. Asercja powinna być spełniona i ponownie powinniśmy ujrzeć zielony kolor. To takie proste!

A jeśli w interfejsie pojawią się nowe metody, to również w niczym to nie przeszkodzi. Wtedy po prostu utworzy się stosownego mocka i zaprogramuje odpowiednie działanie.

Podsumowanie

Powyższe przykłady jasno pokazują dlaczego mocki są takie popularne i dlaczego zazwyczaj są lepszym rozwiązaniem od stubów. Dają programistom bardzo duże możliwości i zapewniają elastyczność w działaniu. Dzięki nim można też przetestować znacznie więcej scenariuszy testowych, oszczędzając przy tym dużo czasu.

The post Testy jednostkowe – Mocki appeared first on Dev Foundry.

]]>
http://devfoundry.pl/testy-jednostkowe-mocki/feed/ 1
Testy jednostkowe – Stuby http://devfoundry.pl/testy-jednostkowe-stuby/ http://devfoundry.pl/testy-jednostkowe-stuby/#comments Mon, 03 Jun 2019 07:24:38 +0000 http://devfoundry.pl/?p=1087 Stuby są wykorzystywane w sytuacji, gdy w testowanej klasie występują pewne zależności. Działanie tych zależności należy obsłużyć, ale problem pojawia się, jeśli nie mamy do nich lub do ich metod bezpośredniego dostępu. Właśnie w tych scenariuszach mogą nam pomóc stuby lub mocki. Ten wpis jest pierwszą częścią miniserii o stubach oraz mockach. Poznamy w nim wady oraz zalety stubów, a także ich ogólną charakterystykę i zastosowanie. W kolejnej części – bliżej przyglądamy się mockom. Scenariusz testowy Naszą bazą kodową, którą ...

Czytaj dalej...Testy jednostkowe – Stuby

The post Testy jednostkowe – Stuby appeared first on Dev Foundry.

]]>
Stuby są wykorzystywane w sytuacji, gdy w testowanej klasie występują pewne zależności. Działanie tych zależności należy obsłużyć, ale problem pojawia się, jeśli nie mamy do nich lub do ich metod bezpośredniego dostępu. Właśnie w tych scenariuszach mogą nam pomóc stuby lub mocki.

Ten wpis jest pierwszą częścią miniserii o stubach oraz mockach. Poznamy w nim wady oraz zalety stubów, a także ich ogólną charakterystykę i zastosowanie. W kolejnej części – bliżej przyglądamy się mockom.

Scenariusz testowy

Naszą bazą kodową, którą chcielibyśmy przetestować, jest aplikacja do zamawiania jedzenia online. Składa się z prostych klas takich jak Account, Order, Cart czy też Meal. W tym wpisie operować będziemy głównie na klasie Account:

class Account {

    private boolean active;
    private Address defaultDeliveryAddress;

    Account() {
        this.active = false;
    }

    Account(Address defaultDeliveryAddress) {
        this.defaultDeliveryAddress = defaultDeliveryAddress;
        if(defaultDeliveryAddress != null) {
            activate();
        } else {
            this.active = false;
        }
    }

    void activate() {
        this.active = true;
    }

    boolean isActive() {
        return this.active;
    }

    Address getDefaultDeliveryAddress() {
        return defaultDeliveryAddress;
    }

    void setDefaultDeliveryAddress(Address defaultDeliveryAddress) {
        this.defaultDeliveryAddress = defaultDeliveryAddress;
    }

}

Jest to prosta klasa typu POJO. Jedyną porcją logiki są konstruktory. Jeśli przy tworzeniu obiektu typu Account skorzystamy z konstruktora bezargumentowego lub też w konstruktorze oczekującym obiektu typu Address przekażemy wartość null, to wtedy utworzone konto będzie nieaktywne, a więc metoda isActive będzie zwracała wartość false. W przeciwnym razie oczywiście zwrócona będzie wartość true.

Nowa funkcjonalność

Teraz przyszedł czas, aby nieco rozbudować naszą aplikację. Chcemy dodać do niej nową funkcjonalność – możliwość pobrania listy klientów z bazy danych, tak aby wysłać im na przykład jakieś wiadomości promocyjne.

Aby to zrobić najpierw tworzymy nowy interfejs, który nazwiemy AccountRepository:

public interface AccountRepository {

    List getAllAccounts();

}

W interfejsie umieściliśmy deklarację jednej metody – getAllAccounts, która ma oczywiście służyć do pobrania kont wszystkich klientów.

Czas na implementację

Kolejnym naturalnym krokiem byłoby utworzenie implementacji powyższego interfejsu. Jednak aby to zrobić rzetelnie, należałoby najpierw przygotować całą konfigurację połączenia z bazą danych, co z kolei zajęłoby sporo czasu, a przecież nie to jest głównym tematem tego wpisu.


Jeśli chcesz prześledzić zmiany krok po kroku w formie wideo, to zapraszamy na nasz kanał na YouTube.


Można też na to spojrzeć w taki sposób, że w naszej aplikacji mamy dostęp tylko i wyłącznie do powyższej metody z interfejsu, a nie do samej jej implementacji. Może być przecież tak, że implementacją zajmuje się inny zespół albo też dane które nas interesują, możemy otrzymywać z jakiegoś innego, zewnętrznego systemu lub API. Załóżmy więc, że nie mamy bezpośredniego dostępu do metody implementującej. Zobaczmy więc, czy mimo takiej niedogodności będziemy w stanie odpowiednio przetestować interesujący nas kod.

Do wyciągania informacji o kontach potrzebny nam będzie serwis. Utworzymy więc stosowną klasę serwisową: AccountService, w którym będziemy mieli jedną zależność. Tą zależnością będzie oczywiście AccountRepository, więc dodajemy ją w konstruktorze:

class AccountService {

    private AccountRepository accountRepository;

    AccountService(AccountRepository accountRepository) {
        this.accountRepository = accountRepository;
    }


}

W powyższej klasie chcielibyśmy umieścić metodę, która będzie zwracała tylko konta aktywne. Nazwiemy ją getActiveAccounts:

List getAllActiveAccounts() {
    return accountRepository.getAllAccounts().stream()
            .filter(Account::isActive)
            .collect(Collectors.toList());
}

Jak widać metoda ta opiera się na danych, które ma zwracać metoda getAllAccounts, będąca implementacją metody z interfejsu AccountRepository. Metoda pobiera konta użytkowników, następnie filtruje je korzystając z metody isActive z klasy Account.

Klasa testowa

Nasz kod jest już gotowy do przetestowania. Tworzymy więc klasę testową AccountServiceStubTest, a w niej metodę getActiveAccounts:

@Test
void getAllActiveAccounts() {

    //given
    AccountService accountService = new AccountService();

W sekcji given chcieliśmy utworzyć obiekt klasy AccountService, ale pojawił się problem, ponieważ w konstruktorze musimy podać klasę, która implementuje interfejs AccountRepository, a my nie mamy instancji takiej klasy.

I właśnie w takiej sytuacji mogą nam pomóc mocki lub stuby. Zajmijmy się zatem stubami.

Czym są stuby?

Stuby to przykładowe implementacje jakiegoś kodu, którego zachowanie chcemy przetestować. Jeśli – tak jak w naszym przykładzie – nie mamy dostępu do prawdziwej metody, która będzie nam zwracała dane, to sami powinniśmy sobie taką metodę utworzyć. Musimy napisać ją w taki sposób, aby zwracała nam zestaw przykładowych danych.

Utwórzmy sobie zatem takiego stuba. Zaczniemy od stworzenia nowej klasy, a jako że stuby są nierozłącznie związane z testami jednostkowymi, to klasy stubowe najlepiej tworzyć w tej samej paczce, w której są normalne klasy testowe. Naszą klasę stubową nazwiemy dość nieoryginalnie – AccountRepositoryStub. Klasa ta powinna implementować interfejs AccountRepository i nadpisywać metodę getAllAccounts:

public class AccountRepositoryStub implements AccountRepository {

    @Override
    public List getAllAccounts() {
        Address address1 = new Address("Kwiatowa", "33/5");
        Account account1 = new Account(address1);

        Account account2 = new Account();

        Address address2 = new Address("Piekarska", "12b");
        Account account3 = new Account(address2);

        return Arrays.asList(account1, account2, account3);
    }

}

Implementacja tej metody jest bardzo prosta: tworzymy nowe konta użytkowników i zwracamy je w postaci listy – zgodnie z deklaracją metody getAllAccounts.

Teraz możemy wrócić do naszego testu i w konstruktorze serwisu przekazać naszego stuba:

@Test
void getAllActiveAccounts() {

    //given
    AccountRepository accountRepositoryStub = new AccountRepositoryStub();
    AccountService accountService = new AccountService(accountRepositoryStub);

A skoro wiemy jakie dane zwraca nasze stub, to wiemy też jaką asercję należy napisać, żeby test przeszedł pozytywnie. Zatem cały test prezentuje się tak:

@Test
void getAllActiveAccounts() {

    //given
    AccountRepository accountRepositoryStub = new AccountRepositoryStub();
    AccountService accountService = new AccountService(accountRepositoryStub);

    //when
    List accountList = accountService.getAllActiveAccounts();

    //then
    assertThat(accountList, hasSize(2));

}

Zakładaliśmy, że zwrócona lista powinna mieć 2 elementy, ponieważ dwa utworzone przez nas w metodzie stubowej konta miały w konstruktorze przekazany adres, a więc tylko te dwa konta są aktywne.

W ten właśnie sposób działają stuby.

Problemy stubowe

Jednak tutaj mamy tylko jeden scenariusz testowy, bo stub zwraca nam jeden, konkretny zestaw danych. A  co jeśli teraz chcielibyśmy przeprowadzić inny test? Co jeśli na przykład chcielibyśmy sprawdzić co będzie, jeśli z repozytorium nie zwrócone zostaną żadne konta aktywne?

W tej chwili nasz stub zwraca 2 konta aktywne i nie można w nim dodać kolejnej metody, ponieważ tylko i wyłącznie ta jedna, jedyna metoda może być implementacją metody z interfejsu. Zatem żeby przetestować inny scenariusz, trzeba by dodać kolejną klasę stubową implementującą interfejs AccountRepository. Następnie w tejże klasie utworzyć utworzyć kolejną metodę która zwracałaby inny zestaw danych.

I jak łatwo się domyślić wkrótce tych klas i metod stubowych mogłoby się zrobić bardzo dużo. A im bardziej skomplikowana metoda, tym więcej klas, i metod.

Jest jeszcze jedna kwestia. A co jeśli do interfejsu dodana zostanie kolejna metoda? Wtedy trzeba by ją implementować we wszystkich klasach stubowych, żeby móc je odpowiednio przetestować i uniknąć błędu kompilacji. Bardzo szybko może się zatem okazać, że klasy stubowe są bardzo ciężkie w utrzymaniu.

Podsumowanie

Dla bardzo prostych klas, metod i przykładów, w których jesteśmy pewni, że nie będą się rozrastać, stuby spełniają swoje zadanie. Jednak przy większej liczbie warunków testowych oraz przy możliwym rozroście interfejsów, są one niestety kiepskim rozwiązaniem. W tych sytuacjach znacznie lepiej skorzystać z mocków, którymi zajmiemy się w kolejnej części tej miniserii.

The post Testy jednostkowe – Stuby appeared first on Dev Foundry.

]]>
http://devfoundry.pl/testy-jednostkowe-stuby/feed/ 2
Testy jednostkowe – JUnit 5 i Mockito 2 – nowy kurs! http://devfoundry.pl/testy-jednostkowe-junit-5-i-mockito-2-nowy-kurs/ http://devfoundry.pl/testy-jednostkowe-junit-5-i-mockito-2-nowy-kurs/#respond Thu, 16 May 2019 13:17:01 +0000 http://devfoundry.pl/?p=1081 Właśnie opublikowaliśmy nasz trzeci wspólny kurs na platformie Udemy: Testy jednostkowe – JUnit 5 i Mockito 2 Testy jednostkowe są jedną z najważniejszych technik, które powinien znać każdy programista, niezależnie od języka w którym tworzy. Nasz kurs jest dedykowany wszystkim, którzy chcą zdobyć lub poszerzyć swoją wiedzę na temat testów jednostkowych, frameworków JUnit 5 oraz Mockito 2, testowania w metodyce Test Driven Development oraz najlepszych praktyk i konwencji w tworzeniu testów jednostkowych.  W kursie dowiesz się między innymi: jak ...

Czytaj dalej...Testy jednostkowe – JUnit 5 i Mockito 2 – nowy kurs!

The post Testy jednostkowe – JUnit 5 i Mockito 2 – nowy kurs! appeared first on Dev Foundry.

]]>
Właśnie opublikowaliśmy nasz trzeci wspólny kurs na platformie Udemy:

Testy jednostkowe – JUnit 5 i Mockito 2

Testy jednostkowe są jedną z najważniejszych technik, które powinien znać każdy programista, niezależnie od języka w którym tworzy.

Nasz kurs jest dedykowany wszystkim, którzy chcą zdobyć lub poszerzyć swoją wiedzę na temat testów jednostkowych, frameworków JUnit 5 oraz Mockito 2, testowania w metodyce Test Driven Development oraz najlepszych praktyk i konwencji w tworzeniu testów jednostkowych.



W kursie dowiesz się między innymi:

  • jak tworzyć dobre testy jednostkowe,
  • jak korzystać z asercji i pracować z frameworkiem JUnit 5,
  • jak korzystać z mocków i pracować z frameworkiem Mockito 2,
  • jak stosować zasady FIRST oraz CORRECT,
  • jak pracować w metodyce Test Driven Development,
  • jak używać metryki Code Coverage

… i dużo więcej! 🙂

Poniżej znajdziecie link z kodem zniżkowym do kursu:

https://www.udemy.com/testy-jednostkowe

Serdecznie zapraszamy! 🙂

The post Testy jednostkowe – JUnit 5 i Mockito 2 – nowy kurs! appeared first on Dev Foundry.

]]>
http://devfoundry.pl/testy-jednostkowe-junit-5-i-mockito-2-nowy-kurs/feed/ 0
JUnit 5 – Extension Model http://devfoundry.pl/junit-5-extension-model/ http://devfoundry.pl/junit-5-extension-model/#comments Tue, 09 Apr 2019 07:04:40 +0000 http://devfoundry.pl/?p=1043 JUnit jest najpopularniejszym frameworkiem (lub – jak kto woli – biblioteką) stosowaną przy tworzeniu testów jednostkowych w Javie. W jego nowej wersji – JUnicie 5, miejsce Rules oraz test runnerów zajął nowy koncept – Extension Model. Daje on bardzo duże możliwości oraz elastyczność, ale dzieje się to kosztem gotowej funkcjonalności, którą zapewniały Rules z JUnita 4. Jak to drzewiej bywało? W JUnicie 4 mieliśmy do dyspozycji test runnery oraz Rules. Test runnery odpowiadały za uruchamianie testów i jeśli nie określiliśmy tego ...

Czytaj dalej...JUnit 5 – Extension Model

The post JUnit 5 – Extension Model appeared first on Dev Foundry.

]]>
JUnit jest najpopularniejszym frameworkiem (lub – jak kto woli – biblioteką) stosowaną przy tworzeniu testów jednostkowych w Javie. W jego nowej wersji – JUnicie 5, miejsce Rules oraz test runnerów zajął nowy koncept – Extension Model. Daje on bardzo duże możliwości oraz elastyczność, ale dzieje się to kosztem gotowej funkcjonalności, którą zapewniały Rules z JUnita 4.

Jak to drzewiej bywało?

W JUnicie 4 mieliśmy do dyspozycji test runnery oraz Rules.

Test runnery odpowiadały za uruchamianie testów i jeśli nie określiliśmy tego inaczej, to domyślnie wykorzystywany był test runner JUnitowy. Jeśli jednak chcieliśmy skorzystać z jakiegoś innego – gotowego lub customowego – test runnera, na przykład bardzo popularny był (i nadal zresztą jest) test runner do frameworka Mockito, to musieliśmy użyć adnotacji @RunWith:

@RunWith(MockitoJUnitRunner.class)

Natomiast Rules były wykorzystywane do tego, aby w klasach i metodach testowych korzystać z jakichś gotowych funkcjonalności.

Załóżmy, że we wszystkich metodach testowych, w wielu klasach testowych chcielibyśmy przed uruchomieniem testów przygotować specjalny plik tekstowy. W obrębie jednej klasy testowej, żeby nie powtarzać takiego kodu w każdej metodzie testowej, można by taki kod umieścić w metodzie z adnotacją @Before (w JUnicie 5 jest to adnotacja @BeforeEach). Dzięki temu odpowiednie działanie byłoby wykonane przed uruchomieniem każdej metody testowej.

Natomiast w tym przykładzie chcemy z takiego kodu korzystać w wielu klasach. Bez sensu byłoby zatem ten sam kod umieszczać w każdej klasie, w metodzie z adnotacją @Before. Wówczas kod nie powtarzałby się co prawda w obrębie klasy, ale w obrębie na przykład paczki – już tak. Żeby temu zaradzić możemy skorzystać z funkcjonalności, którą zapewnia nam zestaw Rules.

Żeby z nich skorzystać, należy najpierw utworzyć instancję interesującej nas klasy (już istniejącej, gotowej z paczki org.junit.rules) i umieścić nad nią adnotację @Rule:

@Rule
private TemporaryFolder temporaryFolder = new TemporaryFolder();

Tutaj mamy przykład klasy TemporaryFolder, dzięki której można utworzyć jakiś plik albo katalog, który jest automatycznie usuwany po zakończeniu danego testu jednostkowego:

temporary folder dev foundry blog programowanie java spring kursy
Przykład kilku metod z klasy TemporaryFolder

I tutaj, jak widać, korzystamy z gotowych, zdefiniowanych metod i możemy to robić w dowolnej ilości klas testowych bez ryzyka powtarzania kodu.


Jeśli chcesz prześledzić zmiany krok po kroku w formie wideo, to zapraszamy na nasz kanał na YouTube.


Wracamy do teraz – Junit 5

W JUnicie 5 mamy za to do dyspozycji Extension Model. Działa on na podobnej zasadzie do Rules, ale zamiast korzystać z gotowej funkcjonalności, mamy do dyspozycji zestaw interfejsów, których metody implementujemy, aby zaczepić się w odpowiednim miejscu life cycle (cyklu życia) danego testu, żeby wykonać tam jakieś działanie.

Cykl życia testu oznacza po prostu kolejność operacji, które są kolejno uruchamiane przez mechanizm przetwarzający daną metodę testową (w przypadku JUNita 5 jest to silnik JUnit Jupiter) w ramach danego testu.

I ta kolejność na przykładzie interfejsów z paczki org.junit.jupiter.api.extension, których metody możemy implementować, prezentuje się mniej więcej tak:

  • TestInstancePostProcessor
  • TestTemplateInvocationContext
  • ExecutionCondition
  • BeforeAllCallback
  • BeforeEachCallback
  • ParameterResolver
  • BeforeTestExecutionCallback
  • AfterTestExecutionCallback
  • TestExecutionExceptionHandler
  • AfterEachCallback
  • AfterAllCallback

Lub jeśli ktoś woli uproszczoną wersję graficzną:

junit 5 extension model dev foundry blog programowanie java spring kursy
JUnit 5 Extension Model – Lifecycle Callbacks

Pomarańczowym kolorem zaznaczone są znane nam adnotacje umieszczane nad metodami, które powinny być uruchamiane przed wszystkimi testami z danej klasy (adnotacja @BeforeAll), przed każdym pojedynczym testem w klasie (@BeforeEach), po każdym pojedynczym teście (@AfterEach) i po wszystkich testach w klasie (@AfterAll).

Natomiast niebieskim kolorem zaznaczone są Callbacks, będące interfejsami z cyklu życia danego testu. I to właśnie ich metody możemy implementować – wówczas będą one uruchamiane w takiej kolejności, jak na grafice powyżej.

Zatem, jeśli na przykład zaimplementujemy metodę interfejsu BeforeEachCallback, to kod takiej metody będzie wykonywany po metodzie oznaczonej adnotacją @BeforeAll, a przed metodą oznaczoną adnotacją @BeforeEach.

Praktyka czyni mistrza

Zobaczmy teraz w jaki sposób możemy to wykorzystać w jakimś przykładzie. Mamy już przygotowaną klasę testową OrderTest:

class OrderTest {

    private Order order;

    @BeforeEach
    void initializeOrder() {
        System.out.println("Before each");
        order = new Order();
    }

    @AfterEach
    void cleanUp() {
        System.out.println("After each");
        order.cancel();
    }

    @Test
    void testAssertArrayEquals() {

        //given
        int[] ints1 = {1, 2, 3};
        int[] ints2 = {1, 2, 3};

        //then
        assertArrayEquals(ints1, ints2);

    }

    @Test
    void mealListShouldBeEmptyAfterCreationOfOrder() {
        //then
        assertThat(order.getMeals(), empty());
        assertThat(order.getMeals().size(), equalTo(0));
        assertThat(order.getMeals(), hasSize(0));
        assertThat(order.getMeals(), emptyCollectionOf(Meal.class));

    }

    @Test
    void addingMealToOrderShouldIncreaseOrderSize() {

        //given
        Meal meal = new Meal(15, "Burger");
        Meal meal2 = new Meal(5, "Sandwich");

        //when
        order.addMealToOrder(meal);

        //then
        assertThat(order.getMeals(), hasSize(1));
        assertThat(order.getMeals(), contains(meal));
        assertThat(order.getMeals(), hasItem(meal));
        assertThat(order.getMeals().get(0).getPrice(), equalTo(15));

    }

    @Test
    void removingMealFromOrderShouldDecreaseOrderSize() {

        //given
        Meal meal = new Meal(15, "Burger");

        //when
        order.addMealToOrder(meal);
        order.removeMealFromOrder(meal);

        //then
        assertThat(order.getMeals(), hasSize(0));
        assertThat(order.getMeals(), not(contains(meal)));

    }

    @Test
    void mealsShouldBeInCorrectOrderAfterAddingThemToOrder() {

        //given
        Meal meal1 = new Meal(15, "Burger");
        Meal meal2 = new Meal(5, "Sandwich");

        //when
        order.addMealToOrder(meal1);
        order.addMealToOrder(meal2);

        //then
        assertThat(order.getMeals(), containsInAnyOrder(meal2, meal1));

    }

    @Test
    void testIfTwoMealListsAreTheSame() {

        //given
        Meal meal1 = new Meal(15, "Burger");
        Meal meal2 = new Meal(5, "Sandwich");
        Meal meal3 = new Meal(11, "Kebab");

        List meals1 = Arrays.asList(meal1, meal2);
        List meals2 = Arrays.asList(meal1, meal2);

        //then
        assertThat(meals1, is(meals2));

    }

}

Znajduje się w niej sześć metod testowych i dwie metody z adnotacjami @BeforeEach oraz @AfterEach.

Są to dość małe testy z prostymi asercjami, których zadaniem jest sprawdzenie działania klasy Order:

class Order {

    private List meals = new ArrayList<>();

    void addMealToOrder(Meal meal) {
        this.meals.add(meal);
    }

    void removeMealFromOrder(Meal meal) {
        this.meals.remove(meal);
    }

    List getMeals() {
        return meals;
    }

    void cancel() {
        this.meals.clear();
    }


}

Powiązaną klasą jest również klasa Meal:

class Meal {

    private int price;
    private String name;

    Meal(int price) {
        this.price = price;
    }

    Meal(int price, String name) {
        this.price = price;
        this.name = name;
    }

}

I załóżmy, że chcielibyśmy napisać kod, który byłby wykonywany przed każdym wywołaniem metody z adnotacją @BeforeEach oraz po każdym wywołaniu metody z adnotacją @AfterEach. Dotyczyłoby to zatem każdego testu jednostkowego w klasie OrderTest.

Żeby to zrobić, musimy najpierw utworzyć nową klasę – BeforeAfterExtension. Ta klasa powinna implementować interfejsy BeforeEachCallback oraz AfterEachCallback (można się posiłkować grafiką powyżej):

public class BeforeAfterExtension implements BeforeEachCallback, AfterEachCallback {

}

Kolejnym krokiem jest zaimplementowanie metod zadeklarowanych w tych interfejsach. Będzie to metoda beforeEach dla interfejsu BeforeEachCallback oraz metoda afterEach dla interfejsu AfterEachCallback.

I żeby niepotrzebnie nie komplikować tego przykładu, w środku tych metod wyświetlimy prosty komunikat:

public class BeforeAfterExtension implements BeforeEachCallback, AfterEachCallback {

    @Override
    public void beforeEach(ExtensionContext extensionContext) {
        System.out.println("Inside before each extension");
    }

    @Override
    public void afterEach(ExtensionContext extensionContext) {
        System.out.println("Inside after each extension");
    }

}

I to tyle! Teraz możemy powrócić do klasy testowej OrderTest.

Jak zastosować dane rozszerzenie?

Aby skorzystać z rozszerzenia, które utworzyliśmy wcześniej, musimy umieścić nad klasą testową specjalną adnotację @ExtendWith. Jako argument tej adnotacji podajemy nazwę naszej klasy rozszerzenia i dodajemy końcówkę .class:

@ExtendWith(BeforeAfterExtension.class)
class OrderTest {

Wówczas takie rozszerzenie będzie stosowane dla całej klasy, a więc dla wszystkich metod testowych. Możemy jednak ograniczyć je tylko do jednej metody. Wtedy adnotacje umieścić należy nad wybraną metodą.

Gdy teraz uruchomimy wszystkie testy z klasy OrderTest, to w konsoli otrzymamy komunikat:

Inside before each extension
Inside after each extension
Inside before each extension
Inside after each extension
Inside before each extension
Inside after each extension
Inside before each extension
Inside after each extension
Inside before each extension
Inside after each extension
Inside before each extension
Inside after each extension

Widać zatem, że para wiadomości:

Inside before each extension
Inside after each extension

została powtórzona sześć razy – tyle ile jest metod testowych w tej klasie. A więc wszystko się zgadza.

Jednak żeby upewnić się, że na pewno metody z naszego rozszerzenia uruchamiają się przed i po metodach z adnotacjami @BeforeEach i @AfterEach, to do nich również dodamy proste komunikaty:

@BeforeEach
void initializeOrder() {
    System.out.println("Before each");
    order = new Order();
}

@AfterEach
void cleanUp() {
    System.out.println("After each");
    order.cancel();
}

Teraz uruchomimy już tylko jeden test – testAssertArrayEquals, żeby nie widzieć wszystkich komunikatów powtórzonych sześciokrotnie:

Inside before each extension
Before each
After each
Inside after each extension

I widzimy, że zgodnie z planem, metody z naszej klasy rozszerzeń – BeforeAfterExtension – były uruchomione odpowiednio przed oraz po metodach z adnotacjami @BeforeEach oraz @AfterEach.

Nie wszystko stracone

Dla osób, które tęsknią za dawną funkcjonalnością Rules, a jednocześnie chcą się przenieść na JUnita 5 – proszę nie panikować! Społeczność programistyczna przygotowała listę silników testowych oraz rozszerzeń, z których można korzystać we własnych projektach: https://github.com/junit-team/junit5/wiki/Third-party-Extensions

Na powyższej liście znajdziemy między innymi pozycję zatytułowaną „JUnit Extensions”: https://glytching.github.io/junit-extensions/index.

Znajduje się tam kilka rozszerzeń, które są odpowiednikami popularnych Rules z JUNita 4. Wśród nich jest także znany nam z początku wpisu TemporaryFolder: https://glytching.github.io/junit-extensions/temporaryFolder

Podsumowanie

Chociaż przykład podany w tym wpisie był dość prosty, to myślę, że dość dobrze pokazuje jak duże możliwości daje Extension Model. I tak naprawdę tylko od nas zależy w jaki sposób zdecydujemy się wykorzystać jego potencjał.

Kod z przykładami do powyższego wpisu znajdziesz na githubie.

The post JUnit 5 – Extension Model appeared first on Dev Foundry.

]]>
http://devfoundry.pl/junit-5-extension-model/feed/ 2
Praca z Optional w Hibernate http://devfoundry.pl/optional-hibernate/ http://devfoundry.pl/optional-hibernate/#comments Thu, 28 Feb 2019 11:35:38 +0000 http://devfoundry.pl/?p=967 Typ Optional jest jednym z ciekawszych dodatków do Javy w ostatnich latach, jednak gdy chcemy użyć go jako typ pola dla encji (obiekt, którego stan przechowywany jest w bazie danych) to czeka nas nieprzyjemna niespodzianka zaserwowana przez Hibernate. Problem z typami opcjonalnymi Mając klasę @Entity public class Book { @Id private Integer id; private String title; private Optional publisher; public Book() { } public Book(Integer id, String title, Optional publisher) { this.id = id; this.title = title; this.publisher = publisher; ...

Czytaj dalej...Praca z Optional w Hibernate

The post Praca z Optional w Hibernate appeared first on Dev Foundry.

]]>
Typ Optional jest jednym z ciekawszych dodatków do Javy w ostatnich latach, jednak gdy chcemy użyć go jako typ pola dla encji (obiekt, którego stan przechowywany jest w bazie danych) to czeka nas nieprzyjemna niespodzianka zaserwowana przez Hibernate.

Problem z typami opcjonalnymi

Mając klasę

@Entity
public class Book {
    
    @Id
    private Integer id;
    private String title;
    private Optional publisher;

    public Book() {
    }

    public Book(Integer id, String title, Optional publisher) {
        this.id = id;
        this.title = title;
        this.publisher = publisher;
    }

    //...gettery
}

Dostaniemy następujący wyjątek już przy starcie aplikacji:

Caused by: org.hibernate.MappingException: Could not determine type for: java.util.Optional

Dzieje się tak, ponieważ Hibernate nie jest w stanie zmapować typu Optional na znany mu typ wspierany przez baze danych.


Jeśli chcesz prześledzić rozwiązanie krok po kroku w formie wideo, to zapraszamy na nasz kanał na YouTube.


Rozwiązanie

Na szczęście nie wszystko stracone. Mianowicie możemy skorzystać z faktu, że nasze zmienne i tak są prywatne, więc ukryte przed całym światem, a dostęp do nich mamy tylko poprzez gettery.

Wystarczy drobna zmiana w kodzie:

@Entity
public class Book {

    @Id
    private Integer id;
    private String title;
    private String publisher;

    public Book() {
    }

    public Book(Integer id, String title, String publisher) {
        this.id = id;
        this.title = title;
        this.publisher = publisher;
    }

    public Optional getPublisher() {
        return Optional.ofNullable(publisher);
    }
}

Zamieniliśmy typ stanu z Optional na String oraz standardowy getter – teraz zwraca on typ Optional, który to jest tworzony przy wywoływaniu gettera.  W ten oto sposób zadowalamy wymagania Hibernate, bo nie ma on problemu ze zmapowaniem na typ tekstowy w dowolnej bazie danych, oraz wymagania biznesowe by publisher był dostępny jako typ opcjonalny.

Jedyną niedogodnością takiego rozwiązania jest to, że jeśli chcemy wewnątrz klasy korzystać z opcjonalnego publisher to musimy albo korzystać z gettera (preferowane), albo sami tworzyć Optional.ofNullable(...).

Rozwiązanie ma jeszcze jedną zaletę. Przy takiej definicji klasy możemy nieco rozszerzyć zwracanie pustego Optional również do sytuacji, gdy mamy pusty tekst („”) jako publisher:

@Entity
public class Book {

    @Id
    private Integer id;
    private String title;
    private String publisher;

    public Book() {
    }

    public Book(Integer id, String title, String publisher) {
        this.id = id;
        this.title = title;
        this.publisher = publisher;
    }

    public Optional getPublisher() {

        if( publisher != null || publisher.isEmpty()) {
            return Optional.empty();
        } else {
            return Optional.ofNullable(publisher);
        }
        
    }
}

 

Jeśli chcesz dowiedzieć się więcej na temat typu Optional polecam nasz poprzedni wpis, a w nagraniu poniżej możesz zobaczyć program demonstrujący zachowanie Optional wraz z Hibernate.

 

Bardzo nam pomożesz udostępniając ten artykuł na swoim facebooku, twitterze czy innym medium społecznościowym, które preferujesz 🙂

The post Praca z Optional w Hibernate appeared first on Dev Foundry.

]]>
http://devfoundry.pl/optional-hibernate/feed/ 1
Krakowskie Wykop Party 2019 http://devfoundry.pl/krakowskie-wykop-party-2019/ http://devfoundry.pl/krakowskie-wykop-party-2019/#respond Tue, 12 Feb 2019 08:40:54 +0000 http://devfoundry.pl/?p=927 Jest nam bardzo miło poinformować, że jesteśmy partnerami oraz sponsorami nagród na tegorocznej edycji Krakowskiego Wykop Party! ( ͡°( ͡° ͜ʖ( ͡° ͜ʖ ͡°)ʖ ͡°) ͡°) Impreza zaczyna się 23. lutego o godzinie 18:00 w krakowskim BarON przy ulicy Stefana Batorego 1. W imieniu organizatorów Krakowskiego Wykop Party 2019 – serdecznie zapraszamy, a wszystkim Mirkom i Mirabelkom życzymy udanej zabawy ( ͡° ͜ʖ ͡°) Na podanej stronie można znaleźć więcej szczegółów dotyczących imprezy: https://krakow2019.wykoparty.pl A tak prezentują się nagrody, a ...

Czytaj dalej...Krakowskie Wykop Party 2019

The post Krakowskie Wykop Party 2019 appeared first on Dev Foundry.

]]>
Jest nam bardzo miło poinformować, że jesteśmy partnerami oraz sponsorami nagród na tegorocznej edycji Krakowskiego Wykop Party! ( ͡°( ͡° ͜ʖ( ͡° ͜ʖ ͡°)ʖ ͡°) ͡°)

wykop party dev foundry blog programowanie java spring kursy

Impreza zaczyna się 23. lutego o godzinie 18:00 w krakowskim BarON przy ulicy Stefana Batorego 1.

W imieniu organizatorów Krakowskiego Wykop Party 2019 – serdecznie zapraszamy, a wszystkim Mirkom i Mirabelkom życzymy udanej zabawy ( ͡° ͜ʖ ͡°)

Na podanej stronie można znaleźć więcej szczegółów dotyczących imprezy: https://krakow2019.wykoparty.pl

A tak prezentują się nagrody, a więc customowe zestawy z kuponami do naszych kursów, które trafią w ręce szczęśliwych Mirków i Mirabelek 🙂

wykop party dev foundry  nagrody blog programowanie java spring kursy

The post Krakowskie Wykop Party 2019 appeared first on Dev Foundry.

]]>
http://devfoundry.pl/krakowskie-wykop-party-2019/feed/ 0