2012-12-28 22 views
10

Potrzebuję przetestować metodę handleIn() za pomocą Mockito.Mockito pomija statyczną metodę testowania

Jednak kod musi wywoływać ten dotychczasowy kod Util.getContextPDO, który jest metodą statyczną.

Należy zauważyć, że w środowisku testowym ten plik Util.getContextPDO zawsze zwraca wyjątek i zamierzam ominąć ten plik Util.getContextPDO(), zawsze zwracając fałszywe IPDO.

public class MyClass { 
    public IPDO getIPDO() 
    { 
    return Util.getContextPDO(); // note that Util.getContextPDO() is a static, not mockable. 
    } 

    public String handleIn(Object input) throws Throwable 
    { 
    String result = ""; 
    IPDO pdo = getIPDO(); 

    // some important business logic. 

    return result; 
    } 
} 

Początkowo myślałem, że to achieveable za pomocą szpiega() klasy „MojaKlasa”, więc mogę kpić wartość zwracaną getIPDO(). Poniżej jest moja pierwsza próba z użyciem szpiega()

@Test 
public void testHandleIn() throws Exception 
{ 
    IPDO pdo = new PDODummy(); 


    MyClass handler = new MyClass(); 
    MyClass handler2 = spy(handler); 

    when(handler2.getIPDO()).thenReturn(pdo); 
    PDOUtil.setPDO(pdo, LogicalFieldEnum.P_TX_CTGY, "test123"); 
    IPDO pdoNew = handler2.getIPDO(); 

    Assert.assertEquals("test123,(PDOUtil.getValueAsString(pdoNew, LogicalFieldEnum.P_TX_CTGY))); 

} 

Jednak kiedy (handler2.getIPDO()) thenReturn (PDO).; rzuca wyjątek, którego chcę uniknąć (ponieważ handler2.getIPDO()) wydaje się wywoływać prawdziwą metodę.

Każdy pomysł na testowanie tej części kodu?

+0

Używamy ** PowerMock ** wraz z ** Mockito ** do wotk ze starszymi wersjami. To okazuje się takie proste, więc postanowiliśmy uniknąć ** PowerMock **, aby walczyć ze spuścizną bardziej skuteczną. –

+1

"Jedynym" problemem z PowerMockiem jest to, że jesteś zmuszony do używania własnego testera, który nie zawsze jest opcją (podczas pisania Testy Android Robolectric, na przykład, które wymagają własnego biegacza robolectric) –

Odpowiedz

10

Zmieniono moje testy do:

@Test 
public void testHandleIn() throws Exception 
{ 
    IPDO pdo = new PDODummy(); 


    MyClass handler = new MyClass(); 
    MyClass handler2 = spy(handler); 

    doReturn(pdo).when(handler2).getIPDO(); 
    PDOUtil.setPDO(pdo, LogicalFieldEnum.P_TX_CTGY, "test123"); 
    IPDO pdoNew = handler2.getIPDO(); 

    Assert.assertEquals("test123,(PDOUtil.getValueAsString(pdoNew, LogicalFieldEnum.P_TX_CTGY))); 

} 

rozwiązana po przeczytaniu Effective Mockito.

+2

"Problem" ze szpiegami, że faktyczna metoda jest wywoływana podczas stubowania. Jedynym sposobem na uniknięcie tego jest użycie formularza doXXXX.when (mock) .somemethod (anyParam()). –

11

Dobrą techniką pozwalającą pozbyć się wywołań statycznych przez interfejs API innej firmy jest ukrywanie wywołania statycznego za interfejsem.

Powiedzmy uczynić ten interfejs:

interface IPDOFacade { 

    IPDO getContextPDO(); 
} 

i mają domyślną implementację że po prostu wywołuje metodę statyczną na 3rd API:

class IPDOFacadeImpl implements IPDOFacade { 

    @Override 
    public IPDO getContextPDO() { 
     return Util.getContextPDO(); 
    } 
} 

Wtedy to po prostu kwestia wstrzykiwanie zależność od interfejsu do MyClass i korzystanie z interfejsu zamiast bezpośrednio interfejsu API innej firmy:

public class MyClass { 

    private final IPDOFacade ipdoFacade; 

    public MyClass(IPDOFacade ipdoFacade) { 
     this.ipdoFacade = ipdoFacade; 
    } 

    public String handleIn(Object input) throws Throwable 
    { 
     String result = ""; 
     IPDO pdo = getIPDO(); 

     someImportantBusinessLogic(pdo); 

     return result; 
    } 

    ... 

} 

W teście urządzenia możesz w prosty sposób kpić z własnego interfejsu, w dowolny sposób i wstrzykiwać go do testowanej jednostki.

Ten

  • eliminuje potrzebę dokonania prywatny pakiet metody prywatne.
  • czyni twoje testy bardziej czytelnymi, unikając częściowego kpiny.
  • stosuje odwrócenie kontroli.
  • oddziela aplikację od określonej biblioteki innej firmy.
+0

Teraz, jak napisać test jednostkowy dla IPDOFacadeImpl.getContextPDO()? – aquacode

+0

Nie, piszesz test integracji dla niego. – bowmore

+0

Dobra odpowiedź. To więcej kodu/plików, ale czuje się dobrze. Pozwala na uniknięcie szpiegów (których Mockito unika), pozwala uniknąć ostrzeżeń o wywołaniu statycznych metod na obiektach instancji i jest zgodny z IoC. – Marquee

1
when(handler2.getIPDO()).thenReturn(pdo); 

rzeczywiście wywołać metodę, a następnie powrót pdo niezależnie.

następuje:

doReturn(pdo).when(handler2).getIPDO(); 

Wrócimy pdo bez wywoływania metody getIPDO().

+0

nadal z doReturn i gdy zostanie wywołana metoda statyczna. – Dish

Powiązane problemy