[jUnit] Testowanie metody

0

Witam

Mam klasę powiedzmy że nazywa się Dane. W tej klasie są jakieś pola typu imie, nazwisko, pesel etc Teraz mam metodę w której jest logika biznesowa wypełniająca te pola (metoda ta jest ween tej klasy ponieważ jest ona związana tylko z tą klasą więc nie wystawiam tego gdzie indziej).

Metoda (publiczna) przyjmuje wielkiego Stringa i wewn robię cuda-wyodrębniam pojedyńcze wyrazy i uzupełniam obiekt. Zwraca tylko true or false. False w przypadku gdy czegoś nie dało się rozdzielić , ztrimować etc.

Z grubsza metoda tak wygląa:

public boolean(String tekst)
{

tutaj się coś dzieje z tekst
i potem:
this.imie = ...

znowu coś się dzieje

this.pesel = ....

i tak dalej
}

Jak taka metodę przetestować w jUnit? Wsadzic Stringa do metody a wynik-sprawdzać wypełnianie obiektu klasy z której wywołano metodę?

0

Wg mnie twoja propozycja jest ok. W końcu w testach chodzi o to, żeby za każdym razem stworzyć świeży obiekt, wywołać na nim jakieś metody, a potem sprawdzić jego stan.

0
@Test
public void testMyMethod(){
  assertTrue(myObj.myMethod("poprwany string"));
  assertFalse(myObj.myMethod("niepoprwany string"));
}

Przy czym daj różne poprawne i nie poprawne stringi tak by pokryć wszystkie przypadki w metodzie.

0

Ale panowie - nie do końca mnie zrozumielisćie.

Metoda ok daje true or false i mogę to przetestować wsadzając w nią dobre lub złe dane.
Ale oprócz boolena przecież są jeszcze inne wyniki: w ciele metody wyodrębniam np imię i nazwisko etc i przypisuje do pól klasy. Jak te wypełnienie pól klasy można zweryfikować?

Coś w stylu:


    @Test
    public void testRozwalenieAdresuNaDrobneIwypelnieniePol() {
        System.out.println("test");
        String tekst = "Mirosław Jagniecki 45-999 Wawa";
        String expResultImie = Mirosław;
        String expResultNazwisko = Jagnicki;
        .
        . 
        .
        boolean result = Utils.indeksPierwszejNapotkanejLitery(tekst);
        if(result)
        {
        assertEquals(expResultImie, this.imie);
        assertEquals(expResultNazwisko, this.nazwisko);
        }

    }

Oczywisćie to nie działa bo takiej składni nie ma. Ale jak to zasymulowac poprawnie?

0

Ja robie tak ze wywoluje metode z roznymi stringami, i po kazdym wywolaniu sprawdzam te pola. Jesli masz gettery, wolasz gettery. Jesli sa to pola private - ja robie je po prostu package (czyli bez modyfikatora). Mam taka konwencje ze testy mam w tych samych pakietach co testowane klasy, i do nazwy dolaczan *Test, zatem mam do takich pol dostep (uzywam mavena i jego konwencji). Nie mam za duzo takich testow, ale czasami sie zdarzaja. Podobnie, zdarza mi sie chciec przetestowac prywatne metody - i wtedy tez zmieniam z private na package (nawet Joshua Bloch w Effective Java mowi ze tak mozna :>). No bo co innego - refleksja?
Mozna tez zrobic tak ze zamiast pol z fragmentami stringa masz jedno pole jakiejs tam innej klasy, ktorej obiekt bierzesz jako parametr konstruktora tej klasy ktora te dane ma przechowywac. W testach mozesz zaposac tam mocka, i weryfikowac z jakimi parametrami byly wywolywane jego metody. Nowe frameworki typu Mockito umieja robic mocki klas (nie final), wiec nie potrzeba interfejsow. Ale jakos wydaje mi sie to troche przesadzone...

0

@::.

"Ja robie tak ze wywoluje metode z roznymi stringami, i po kazdym wywolaniu sprawdzam te pola. Jesli masz gettery, wolasz gettery."

Dokładnie tak to sobie wyobrażam tylko nie umiem tego jakoś zainicjalizować- obiektu.
Mozesz mi napisac taki prosty test do metody przypiszDane?? Bym wiedział o co się zachaczyć?

Przykładowe stringi niech bedą:
"jan waleń warszawa"
"janwaleńwarszawa"

package temp;

public class TestExample {

    private String _imie;
    private String _nazwisko;
    private String _miejscowosc;

    public boolean przypiszDane(String txt) {
        try {
            this._imie = txt.substring(0, txt.indexOf(" "));
            this._miejscowosc = txt.substring(txt.lastIndexOf(" ") + 1, txt.length());
            this._nazwisko = txt.substring(txt.indexOf(" ") + 1, txt.lastIndexOf(" "));
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    public String getImie() {
        return _imie;
    }

    public String getMiejscowosc() {
        return _miejscowosc;
    }

    public String getNazwisko() {
        return _nazwisko;
    }

}
0
    @Test
    public void testRozwalenieAdresuNaDrobneIwypelnieniePol() {
        String tekst = "Mirosław Jagniecki 45-999 Wawa";
        String expResultImie = "Mirosław";
        String expResultNazwisko = "Jagnicki";
        TestExample o = new TestExample();
        boolean ret = o.przypiszDane(tekst);
        assertTrue(ret);
        assertEquals(expResultImie, o.getImie());
        assertEquals(expResultNazwisko, o.getNazwisko());
    }

Przy okazji - proponuję zamiast metody przypiszDane utworzyć konstruktor z argumentem.

0

o to mi chodziło - nie wiedziałem własnie ze można tak wprost stworzyć obiekt o i norlmalnie odwoływac się do metod tej klasy. Dzięki!

0
lipkerson napisał(a)

o to mi chodziło - nie wiedziałem własnie ze można tak wprost stworzyć obiekt o i norlmalnie odwoływac się do metod tej klasy. Dzięki!

A dlaczego mialo by to byc niemozliwe?
Od siebie moge dodac jeszcze tylko, ze fajnie mozna to robic za pomoca TestNG. Mianowicie:

public class SomeTest {

@DataProvider(name = "stringsProvider")
Object[][] provideStrings() {
     return new Object[][] {
        {"string a", "string", "a"},
        {"string b", "string", "b"},
        {"string c", "string", "c"}
};
}

@Test(dataProvider = "stringsProvider")
public void testPrzypiszDane(String string, String expected1, String expected2) {
     TestClass o = new SomeTest();
     assertTrue(o.someMethod(string));
     assertEquals(expected1, o.getPart1());
     assertEquals(expected2, o.getPart2());
}
}

W ten sposob masz tylko 2 metody, a wiele testow. TestNG poprawnie pokaze ze sa 3 rozne testy, w drzewku / raporcie ladnie rozdzieli wszystko. Mysle ze jest dosc jasne, dlaczego metoda prodivera zwraca tablice tablic - kazy element jest tablica, ktora jest nastepnie mapowana na parametry metody ktora od danego providera zalezy. Parametrow jak i zastosowan jest bez liku.
Nie wiem czy to jest w Junit4, nie wiem tez czego uzywasz, na podstawie samych adnotacji nie potrafie stwierdzic.

0
__krzysiek85 napisał(a)

Przy okazji - proponuję zamiast metody przypiszDane utworzyć konstruktor z argumentem.

Jest bardzo wielu znanych w swiatku Java ludzi ktorzy sie z tym kompletnie nie zgodza. Dosc popularne jest stwierdzenie ze konstruktor nie powinien robic nic, co najwyzej przypisywac zaleznosci do pol. Ty proponujesz aby konstruktor wykonywal jakastam logike biznesowa.

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