• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Testowanie metod

Object Storage Arubacloud
0 głosów
227 wizyt
pytanie zadane 25 czerwca 2018 w Java przez kamil159 Nowicjusz (180 p.)

Witam, stwierdziłem że to już najwyższy czas na to żeby zacząć pisać testy. Poczytałem pooglądałem i takie testy napisałem (heh)

class ArticleServiceTest {

    @InjectMocks
    private ArticleService articleService;
    @Mock
    private ArticleRepository articleRepository;
    @Mock
    private ArticleVoteRepository articleVoteRepository;
    @Mock
    private UserService userService;
    private Article article;
    private User user;
    private ArticleVote vote;
    private ArticleVote updatedVote;


    @BeforeEach
    void setUp() {
        MockitoAnnotations.initMocks(this);

        user = new User();
        user.setUsername("user");
        user.setPassword("password");

        article = new Article();
        article.setId(1L);
        article.setTitle("Testing");
        article.setVotes(0);
        article.setUser(user);
        user.getAddedArticles().add(article);

        vote = new ArticleVote();
        vote.setVoteType(VoteType.VOTE_UP.toString());
        vote.setUser(user);
        vote.setArticle(article);

        updatedVote = new ArticleVote();
        updatedVote.setArticle(article);
        updatedVote.setUser(user);

        Mockito.when(userService.isUserLogged()).thenReturn(true);
        Mockito.when(userService.getLoggedUser()).thenReturn(user);
        Mockito.when(articleRepository.getOne(article.getId())).thenReturn(article);
        Mockito.when(articleRepository.save(article)).thenReturn(article);
        Mockito.when(articleVoteRepository.findByUserAndArticle(user,article)).thenReturn(vote);

    }

    @Test
    void UsersFirstVote() {
        Assert.assertEquals( 1, articleService.voteForArticle(vote).getVotes());
    }


    @Test
    public void UpdateVoteFromUpToDown(){
        article.setVotes(1);
        user.getArticleVotes().add(vote);

        updatedVote.setVoteType(VoteType.VOTE_DOWN.toString());

        Assert.assertEquals(-1, articleService.voteForArticle(updatedVote).getVotes());
    }

    @Test
    public void UpdateVoteFromUpToUp(){
        article.setVotes(1);
        user.getArticleVotes().add(vote);

        updatedVote.setVoteType(VoteType.VOTE_UP.toString());

        Assert.assertEquals(1, articleService.voteForArticle(updatedVote).getVotes());
    }
}

Chciałbym żeby mi ktoś teraz podpowiedział czy te testy są dobrze napisane.

A po drugie to w sumie nie wiem do jakich metod powinienem pisać testy, z tymi wyżej to było proste czy pisac czy nie pisać bo troche logiki tam jest i różne sytuacje, ale na przykład tutaj już nie wiem czy jest sens

public User getUserById(Long userId) {
    return userRepository.getOne(userId);
}
public List<Article> getUserArticles(Long userId) {
        User user = userRepository.getOne(userId);
        return user.getAddedArticles();
    }

Albo tutaj

public User registerUser(User user) {
        if (!isUsernameAvailable(user.getUsername())) {
            return user;
        }
        user.setPassword(new BCryptPasswordEncoder().encode(user.getPassword()));
        UserRole role = new UserRole();
        role.setRole(Roles.ROLE_USER.toString());
        user.getRoles().add(role);
        
        return userRepository.save(user);
    }

    private boolean isUsernameAvailable(String username) {
        User user = userRepository.findByUsername(username);
        if (user == null) {
            return true;
        }
        return false;
    }

Podejrzewam że tutaj już powinny być ale jak je przetestować? Mam dwie sytuacje - kiedy username jest dostępny i kiedy nie ale później co sprawdzać w takim teście? Czy user ma role? Bo przecież nie sprawdzę czy się zapisał do db skoro mam zmockowane repo

3 odpowiedzi

+1 głos
odpowiedź 25 czerwca 2018 przez ShiroUmizake Nałogowiec (46,300 p.)
Inject stosujmey przy mockach, gdy nie mamy bezpośrednio dostępu do core Frameworkach. Możesz odpalić memorybase jak HSQL. Testuj punkty krytyczne aplikacji (komunikacja, filtracja, dostępy).

Dlaczego w setup, masz wrzucone warunki testu?? Ograniczasz możliwość dziedziczenia setupa.
+1 głos
odpowiedź 25 czerwca 2018 przez Wiciorny Ekspert (269,710 p.)

po pierwsze: Unitowy test ma testować  jedną klasę 

po drugie nie zaczynamy nazw metod z dużej literki .... 

po trzecie, testujemy 1 funkcjonalność ZAWSZE  w jednej metodzie tesetowej ... nie więcej

public User getUserById(Long userId) {
    return userRepository.getOne(userId);
}

jest sens pisania testu, test musi sprawdzić czy metoda zwraca "usera" ... co jeśli go nie zwróci ? 

Testy zawsze musimy pisać do metod/funkcjonalność którę coś nam zwracają np. jakiś rezultat lub "Zasób"  w celu zabezpieczenia aplikacji przed możliwymi błędami w przyszłości kiedy nagromadzi się sporo kodu 

public User registerUser(User user) {
        if (!isUsernameAvailable(user.getUsername())) {
            return user;
        }
        user.setPassword(new BCryptPasswordEncoder().encode(user.getPassword()));
        UserRole role = new UserRole();
        role.setRole(Roles.ROLE_USER.toString());
        user.getRoles().add(role);
         
        return userRepository.save(user);
    }
 
    private boolean isUsernameAvailable(String username) {
        User user = userRepository.findByUsername(username);
        if (user == null) {
            return true;
        }
        return false;
    }

Nie testujesz LOGIKI WEWNĘTRZNEJ METODY...

testujesz metode... ma zwrócić Usera, to testujesz na "Fake-owych" danych czy metoda zaleznie od wprowadzenia zamockowania przez ciebie danych faktycznie zwróci Ci Usera.... ( logika wewnętrzna Cię nie interesuje )

w drugim przypadku testujesz zależnie od podanego "STRING USERNAME"  wartość prawdy/fałszu 

okej ale dla takiego typu metod robimy dwa podejścia : 

shouldReturnFalseForAvaiableUser () - testowanie przypadku false czyli mokujesz dane tak żeby uzyskać FALSE i takiego rezultatu się spodziewasz, analogicznie 

shouldReturnTrueForAvaiableUser () testowanie przypadku TRUE czyli mokujesz dane tak żeby uzyskać TRUE i

komentarz 25 czerwca 2018 przez kamil159 Nowicjusz (180 p.)

po pierwsze: Unitowy test ma testować  jedną klasę 

A nie metodę? 

po trzecie, testujemy 1 funkcjonalność ZAWSZE  w jednej metodzie tesetowej ... nie więcej

No mam po jednej... czy nie?

public User getUserById(Long userId) {
    return userRepository.getOne(userId);
}

jest sens pisania testu, test musi sprawdzić czy metoda zwraca "usera" ... co jeśli go nie zwróci ? 

 Czyli coś takiego ma być w teście?

@Test
void shouldReturnUser() {
    User user = new User();
    user.setUsername("username");
    user.setPassword("password");
    user.setId(1L);
    Mockito.when(userRepository.getOne(user.getId())).thenReturn(user);
    Assert.assertNotNull(userService.getUserById(user.getId()));
}

 

shouldReturnFalseForAvaiableUser () - testowanie przypadku false czyli mokujesz dane tak żeby uzyskać FALSE i takiego rezultatu się spodziewasz, analogicznie 

shouldReturnTrueForAvaiableUser () testowanie przypadku TRUE czyli mokujesz dane tak żeby uzyskać TRUE i

Mam przetestować osobno prywatną metodę?  Czytałem że prywatne metody powinno się testować przez publiczne

–1 głos
odpowiedź 25 czerwca 2018 przez mbabane Szeryf (79,280 p.)
public User getUserById(Long userId) {
    return userRepository.getOne(userId);
}

To możesz przetestować w taki sposób, że za pomocą Mockito, sprawdzasz czy jest wywoływana metoda getOne().

W tej rejestracji to możesz albo użyć bazy testowej tak jak proponuje ShiroUmizak lub stworzyć odpowiednie mocki i sprawdzić czy metoda zachowuje się tak jak powinna.

Takie testy mimo, że są bardzo trywialne, mogą się przydać w przyszłości, np. nich ktoś usunie z metody isUsernameAvailable() tego if'a, jeśli nie będzie to złapane w testach, będzie duży problem.

komentarz 25 czerwca 2018 przez Wiciorny Ekspert (269,710 p.)

testować mamy funkcjonalnosć metody... jeśli zwraca nam Usera- to testujemy to tak, że za pomocą mock'a lub fake data... spodziewamy się że rezultat "USER" jest taki jaki -  EXPECTED 

komentarz 25 czerwca 2018 przez mbabane Szeryf (79,280 p.)

jeśli zwraca nam Usera

Zasadniczo to nam testuje sama Java i IDE bo jak zmienię na void to wywali się wszystko, ale ok, rozumiem co masz na myśli - chodzi Ci o to czy jak proszę o usera X to nie zwraca nam usera Y

A teraz robię tak:

public User getUserById(long id)
{
    return new User();
}

Metoda nadal zwraca usera, bez odpowiedniego mocka, sprawdzenia czy dana metoda jest wywoływana takie coś nie zostanie wychwycone - funkcjonalność spełniona metoda zwraca Usera.

I nie wiem czym sobie zasłużyłem na downwote...

komentarz 25 czerwca 2018 przez Wiciorny Ekspert (269,710 p.)
edycja 25 czerwca 2018 przez Wiciorny

chodzi Ci o to czy jak proszę o usera X to nie zwraca nam usera Y

no nie do końca bo test-CASE będzie miał 2 przypadki :

shouldReturnUser() -  zwróci tego użytkownika co podałeś w mocku NA BAZIE ID :) tylko i wyłącznie 

shouldNotReturnUser() - nie zwróci użytkownika jeśli zamokujesz np użytkownika o id  1 a poprosisz o id 2 ... powinno być true, i nie zwrócić usera :) 

właśnie to jest problem ludzi którzy "NIE SĄ TESTERAAMI " a developerami i doczynienia maja raptem tylko z unitem ... 

swoją drogą 

ktoś usunie z metody isUsernameAvailable() tego if'a, jeśli nie będzie to złapane w testach, będzie duży problem

nie to jest celem testu... i takie testy implementowane są na bazie assercji ze Springa a nie unitowych testów, testy nie dotyczą wewnetrznej funkcjonalności bo jak zaimplementujesz to OPTIONALEM to ifa Ci nie trzeba :)  

komentarz 25 czerwca 2018 przez mbabane Szeryf (79,280 p.)

No, tak przypadek kiedy w bazie nie ma danego usera.

takie testy implementowane są na bazie assercji ze Springa  

Tak na poziomie asercji - w sumie nie wiem jak inaczej.

komentarz 25 czerwca 2018 przez Wiciorny Ekspert (269,710 p.)

Podobne pytania

0 głosów
1 odpowiedź 142 wizyt
pytanie zadane 3 sierpnia 2018 w Java przez kamil159 Nowicjusz (180 p.)
+1 głos
1 odpowiedź 670 wizyt
pytanie zadane 16 października 2021 w Java przez p_wika Nowicjusz (190 p.)
0 głosów
1 odpowiedź 375 wizyt
pytanie zadane 4 maja 2021 w Java przez janyczek Początkujący (360 p.)

92,555 zapytań

141,402 odpowiedzi

319,539 komentarzy

61,938 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...