Kurs Java od podstaw Tydzień 4

Omówienie aplikacji domowej – część I

Omówienie aplikacji domowej – część I

Witamy się w kolejnym tygodniu kursu – już czwartym. Klasycznie już zaczniemy od omówienia zadania w ramach tworzenia aplikacji. No to omówmy jak ja do tego podszedłem.

ProductService

W lekcji o interfejsach otrzymałeś zadanie, aby stworzyć interfejs ProductService, napisać do niego testy oraz zadbać o jego implementację.

Interfejs ProductService

Otrzymałeś całą listę metod jaką ma posiadać interfejs:

zwrócenie wszystkich Products – getAllProducts() – czyli zwracamy listę produktów

List<Product> getAllProducts();

zwrócenie ilości produktow na liście – getCountProducts()

Integer getCountProducts();

zwrócenie Product poprzez productName – jeżeli nie istnieje to null

Product getProductByProductName(String productName);

sprawdzenie czy ilość produktu jest większa od 0 dla konkretnego productName

boolean isProductOnWarehouse(String productName);

sprawdzenie czy produkt o podanym productName istnieje – przeszukujemy listę w poszukiwaniu productName

boolean isProductExist(String productName);

sprawdzenie czy produkt o podanym id istnieje – przeszukujemy listę w poszukiwaniu id

boolean isProductExist(Long productId);

I cały nasz interfejs wygląda tak:

package api;

import entity.Product;

import java.util.List;

public interface ProductService {
    List<Product> getAllProducts();
    Integer getCountProducts();
    Product getProductByProductName(String productName);
    boolean isProductOnWarehouse(String productName);
    boolean isProductExist(String productName);
    boolean isProductExist(Long productId);
}

Zauważ, że metody mogą mieć takie same nazwy o ile ich argumenty się różnią – ilość lub typ.

Testy

Skoro mamy już interfejs to można napisać do nich testy. 😉 Dla ProductService stworzyłem aż 12 testów – omówię kilka z nich w takim razie. Reszta jest tworzona analogicznie.

Do tego celu stworzyłem klasę ProductServiceTest w pakiecie: /src/test/java/service – ważne, aby klasy znajdowały się w tych samych pakietach.

Pierwszy test jest odpowiedzialny za sprawdzenie czy getAllProducts działa poprawnie.

@Test
public void testGetAllProductsPositive() {
    List<Product> products = new ArrayList<Product>();
    products.add(new Cloth(1l, "T-SHIRT", 35.0f, 0.3f, "Black", 4, "XL", "COTTON"));
    products.add(new Boots(1l, "T-SHIRT", 35.0f, 0.3f, "Black", 4, 38, true));

    ProductServiceImpl userService = new ProductServiceImpl(products);
    List<Product> listFromTestClass = userService.getAllProducts();

    Assert.assertEquals(products, listFromTestClass);
}

Czyli na początku tworzymy liste, dodajemy do niej dwa produkty, inicjalizujemy ProductServiceImpl, wywołujemy getAllProducts i porównujemy obie listy.

Następny test odpowiedzialny jest za sprawdzenie czy ilość produktów się zgadza:

@Test
public void testGetCountProductsWithProducts() {
    List<Product> products = new ArrayList<Product>();
    products.add(new Cloth(1l, "T-SHIRT", 35.0f, 0.3f, "Black", 4, "XL", "COTTON"));
    products.add(new Boots(2l, "Boots", 35.0f, 0.3f, "Black", 4, 38, true));

    ProductServiceImpl productService = new ProductServiceImpl(products);
    final int result = productService.getCountProducts();

    Assert.assertEquals(2, result);
}

Dajemy listę z dwoma elementami dlatego oczekujemy rezultatu równego 2.

Następny test jest odpowiedzialny za szukanie produktu po productName.

@Test
public void testGetProductByProductNameWhenNoExist() {
    List<Product> products = new ArrayList<Product>();
    Product cloth = new Cloth(1l, "T-SHIRT", 35.0f, 0.3f, "Black", 4, "XL", "COTTON");
    products.add(cloth);
    products.add(new Boots(2l, "Boots", 35.0f, 0.3f, "Black", 4, 38, true));

    ProductServiceImpl productService = new ProductServiceImpl(products);
    final Product product = productService.getProductByProductName("JAKIS-PRODUKT");

    Assert.assertEquals(null, product);
}

Do listy dodajemy dwa obiekty, później szukamy produktu po nazwie „JAKIS-PRODUKT” -czyli nazwy, która nie istnieje na liście produktów – w takim razie powinniśmy otrzymać null.

Następny test jest odpowiedzialny za sprawdzenie czy produkt jest na stanie magazynowym – czyli jego ilość jest większa od 0.

@Test
public void testIsProductOnWareHouseWhenIsNot() {
    List<Product> products = new ArrayList<Product>();
    products.add(new Boots(2l, "Boots", 35.0f, 0.3f, "Black", 0, 38, true));

    ProductServiceImpl productService = new ProductServiceImpl(products);
    final boolean isProductOnWareHouse = productService.isProductOnWarehouse("Boots");

    Assert.assertFalse(isProductOnWareHouse);
}

Na początku dodajemy do listy produkt Boots, gdzie jego ilość jest równa 0. Dlatego na koniec oczekujemy fałszu – czyli produktu nie ma na magazynie.

Następny test sprawdza dla nas czy productName istnieje:

@Test
public void testIsProductExistByNameWhenExist() {
    List<Product> products = new ArrayList<Product>();
    products.add(new Boots(2l, "Boots", 35.0f, 0.3f, "Black", 0, 38, true));

    ProductServiceImpl productService = new ProductServiceImpl(products);
    final boolean isProductExist = productService.isProductExist("Boots");

    Assert.assertTrue(isProductExist);
}

Czyli podajemy obiekt Boots o nazwi Boots i później przeszukujemy listę po tej nazwie. Oczekujemy prawdy, w końcu taki produkt istnieje.

Analogicznie sprawdzamy czy produkt istnieje po ID – tym razem przypadek negatywny, czyli nie znajdziemy produktu

@Test
public void testIsProductExistByIdWhenNoExist() {
    List<Product> products = new ArrayList<Product>();
    products.add(new Boots(2l, "Boots", 35.0f, 0.3f, "Black", 0, 38, true));

    ProductServiceImpl productService = new ProductServiceImpl(products);
    final boolean isProductExist = productService.isProductExist(5l);

    Assert.assertFalse(isProductExist);
}

Dodajemy produkt o id 2 – a szukamy o id 5. Oczywiście oczekujemy fałszu, w końcu taki produkt nie istnieje.

To na tyle omówienia testów, spójrz na moje testy – zostało ich jeszcze kilka do omówienia. Są to przeciwne przypadki – jeżeli omówiłem przypadek pozytywny to prawdopodobnie został jeszcze przypadek negatywny. Do każdej metody starałem się dodać po dwa testy – właśnie jeden, który np. znajdzie czyli zwróci prawdę, a drugi będzie oczekiwał np. nulla. Dzięki temu mam sprawdzone dwa skrajne przypadki – znajdzie i nie znajdzie.

Implementacja

Skoro mamy już napisane testy to oczywiście nie przejdą one, gdy nie stworzymy do niej implementacji. W tym celu stworzyłem klasę ProductServiceImpl, która implementuję interfejs ProductService, a zarazem jego wszystkie metody, które musimy uzupełnić. 😉

Stworzyłem konstruktor bezparametrowy, który pozwoli stworzyć obiekt od razu z pustą listą:

public ProductServiceImpl() {
    products = new ArrayList<Product>();
}

Oraz konstruktor parametrowy, który pozwala na dostarczenie już swojej listy produktów.

public ProductServiceImpl(List<Product> products) {
    this.products=products;
}

I przejdźmy do omawiania metod.

Metoda zwracająca wszystkie produktu – jest odpowiedzialna po prostu za zwrócenie całej listy.

public List<Product> getAllProducts() {
    return products;
}

Metoda odpowiedzialna za zwrócenie liczby produktów – zwraca rozmiar listy:

public Integer getCountProducts() {
    return products.size();
}

Wyszukiwanie produktu po productName polega na przejściu pętlą foreach po całej liście i zwrócenia tego, który ma taki sam productName – w przeciwnym wypadku zwracamy null.

public Product getProductByProductName(String productName) {
    for(Product product : products) {
        if (product.getProductName().equals(productName)) {
            return product;
        }
    }

    return null;
}

Sprawdzenie czy produkt o danym productName istnieje – przechodzimy po wszystkich elementach listy i porównujemy productName przy użyciu metody equals, o której powiem w tym tygodniu.

public boolean isProductExist(String productName) {
    for(Product product : products) {
        if (product.getProductName().equals(productName)) {
            return true;
        }
    }
    return false;
}

Analogicznie działa metoda szukająca produktu o danym productId.

public boolean isProductExist(Long productId) {
    for(Product product : products) {
        if (product.getId().equals(productId)) {
            return true;
        }
    }
    return false;
}

Sprawdzenie czy produkt jest na magazynie odbywa się przez przejście po wszystkich elementach listy aż do napotkania takiego, który ma taki sam productName oraz ilość sztuk większą od zera.

public boolean isProductOnWarehouse(String productName) {
    for(Product product : products) {
        if (isProductExist(productName) && product.getProductCount() > 0) {
            return true;
        }
    }
    return false;
}

Zauważ, że wykorzystałem wcześniej napisaną metodę isProductExist – w końcu warunkiem koniecznym wystąpienia produktu na magazynie jest w ogóle jego istnienie w naszym systemie – czyli na liście. Jeżeli faktycznie productName istnieje to dopiero sprawdzamy czy jego count jest większy od 0.

Staraj jak najczęściej używać metod, które już wcześniej napisałeś. Twój kod będzie dużo czytelniejszy. 😉

Końcówka…

Oczywiście po napisaniu tego wszystkiego musimy sprawdzić czy testy faktycznie przechodzą komendą

mvn install

I jeżeli testy faktycznie przechodzą to możemy stworzyć commita np.:

git add *
git commit -m "Implemented product service"

I ewentualnie od razu wypchnąć je na zdalny serwer:

git push origin master

Podsumowanie

Moje rozwiązanie problemu, możesz obejrzeć tutaj. 😉

I to tyle co do części pierwszej zadania – czyli stworzenia ProductService. W kolejnym wpisie omówię kolejne Twoje zadanie czyli ProductDao oraz UserDao. 😉

Subscribe
Powiadom o
guest
2 komentarzy
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Dave
Dave
7 dni temu

wydaje mi się, że poprzednia kolorystyka była bardziej żywa 😀