piątek, 17 września 2010

Testowanie metod prywatnych w javie

Pomijając dysputy o tym, czy w ogóle można, czy też nie można testować metod prywatnych. Zamieszczam przykład jak to zrobić jeśli, ktoś będzie w sytuacji, że po prostu musi to zrobić.

Mamy przykładowo klasę do stestowania:
public class SomeClass{
    ...
    private Boolean someMethod(String s, Integer i){
        ...
    }    
} 

Podczas testów używam mechanizmu refleksji i schematu given/when/then, o którym więcej można posłuchać tutaj. Przykładowa klasa testująca metodę prywatną z klasy SomeClass może być następująca:
import static org.fest.assertions.Assertions.assertThat;
import static org.fest.assertions.Fail.fail;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import org.junit.Before;
import org.junit.Test;

public class SomeClassTest {
    
    SomeClass someClass;
    
    @Before
    public void init() {
        someClass = new SomeClass();    
    }
    
    @Test
    public void shouldDoSomethingGood() {        
        //given
        //sekcja przygotowująca
        
        //when
        Boolean result=null;
        try {
            result = invokePrivateMethodSomeMethod("test",10);
        } 
        catch (Exception e) {
            e.printStackTrace();
            fail("Nie oczekujemy wyjątku");
        }        
        //then
        assertThat(result).isTrue();    
    }
    
    private Boolean invokePrivateMethodSomeMethod(String s, Integer i) throws SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException{
    
        Class[] args =  {String.class, Integer.class}; 
        //niestety musimy wpisać nazwę metody jako string - niezbyt dobre rozwiązanie w przypadku późniejszego refaktoringu
        Method method = SystemUtils.class.getDeclaredMethod("someMethod", args);
        method.setAccessible(true);
        Object[] argObjects = {s,i};
        return (Boolean) method.invoke(someClass, argObjects);
    }
}

2 komentarze:

  1. Oczywiście że private metod nie testujemy. Ale jak już się uparłeś to zamiast łapać wyjątek po prostu
    zadeklaruj

    public void shouldDoSomethingGood() throws Exception

    Otrzymasz czytelniejszy kod + jasny komunikat co się stało (orginalny exception, zamiast exception z fail)

    OdpowiedzUsuń
  2. temat roztrzaskałem na drobne kawałki tutaj: http://javaexpress.pl/numer/numer-3/testowanie-metod-prywatnych/ :)

    zapraszam do lektury

    --
    Tomek Kaczanowski
    http://kaczanowscy.pl/tomek

    OdpowiedzUsuń