2013-08-20 18 views
13

Pracuję trochę nad odziedziczonym kodem. pisałem test, który ma złapać NullPointerException (bo próbuje wywołać metodę od null object)Mockito, gdy(). ThenReturn wywołuje metodę niepotrzebnie

@Test(expected=NullPointerException.class) 
public void checkXRequirement_NullProduct_AddAction_ShouldThrowNullPointerException() throws CustomException { 
    Site site = mock(Site.class); 
    Product product = null; 
    when(BasketHelper.getAction(request)).thenReturn(0); 
    when(BasketHelper.getActionProduct(site, request)).thenReturn(product); 
    BasketHelper.requiresX(request, site); 

} 

odpowiednich metod i zmiennych:

public static final int ACTION_ADD = 0; 
public static final int ACTION_DELETE = 1; 

protected static int getAction(HttpServletRequest a_request) { 
    String sBuyProduct = a_request.getParameter(ATTRIBUTE_NAME_BUY_PRODUCT); 
    String sBuyProduct = a_request.getParameter(ATTRIBUTE_NAME_BUY_PRODUCT); 

    if (sBuyProduct != null) iAction = ACTION_ADD; 
    else (sDelProduct != null) iAction = ACTION_DELETE; 

    return iBasketAction 
} 

protected static Product getActionProduct(Site a_site, HttpServletRequest a_request) { 

    String sBuyProduct = a_request.getParameter(ATTRIBUTE_NAME_BUY_PRODUCT); 
    String sDelProduct = a_request.getParameter(ATTRIBUTE_NAME_DEL_PRODUCT); 
    String sProduct = null; 

    switch (getBasketAction(a_request)) { 
     case BASKET_ACTION_ADD: 
     sProduct = sBuyProduct; 
    break; 
     case BASKET_ACTION_DELETE: 
     sProduct = sDelProduct; 
    break; 
    } 

    int iProductId; 
    try { 
     iProductId = Integer.parseInt(sProduct); 
    } catch (NumberFormatException nbrEx) { 
     return null; 
    } 

    Product prod = getProductById(iProductId); 

    if (prod.isMasterProduct()) { 
     prod = getChildProduct(prod, a_site, a_request); 
    } 

    return prod; 
} 


public static boolean requiresX(HttpServletRequest request, Site site) throws CustomException { 
    try{ 
    if (getAction(request) == ACTION_ADD) { 
    Product prod = getActionProduct(site, request); 
    return prod.getType().isRequiredX(); 
    } 
    } catch(NullPointerException exception) { 
    log.error("Error Message", exception); 
    } 
    return false; 
} 

Wynikiem jUnit od biegania test jest porażką z ślad stosu:

java.lang.Exception: Unexpected exception, expected<java.lang.NullPointerException> but was<org.mockito.exceptions.misusing.WrongTypeOfReturnValue> 
Caused by: org.mockito.exceptions.misusing.WrongTypeOfReturnValue: 
Integer cannot be returned by getParameter() 
getParameter() should return String# 

Czy ja źle zinterpretować jak gdy() thenReturn ma pracować on. re? Chcę tylko, aby getAction zwracało 0, a getActionProduct zwracało wartość null, gdy jest wywoływane. Najwyraźniej funkcja getParameter() jest wywoływana i nie wiem, dlaczego dokładnie.

+0

Czy możesz pokazać 'getProduct()'? –

+0

W innych wiadomościach .... Rozumiem, dlaczego napisałbyś ten rodzaj testu, aby powielić problem. Jednak prawdziwym testem tutaj powinno być sprawdzenie, czy jeśli '' '' produkt''' ma wartość null, nie jest wywoływana metoda '' 'needsX'''''. O ile Twój odziedziczony kod nie używa npe do kontrolowania przepływu kodu?W takim przypadku - wyrwij to również. – OceanLife

+0

Myślę, że masz rację. zmiana warunku w metodzie requireX jest prawdopodobnie dobrym pomysłem. –

Odpowiedz

13

Mockito nie może symulować metody statycznej. Twoje, gdy sprawdzenie jest nieważne:

when(BasketHelper.getAction(request)).thenReturn(0); 
    when(BasketHelper.getActionProduct(site, request)).thenReturn(product); 

To kolejny powód, dla którego chcemy ograniczyć stosowanie metody statycznej, ponieważ trudno jest kpić.

Nie ma łatwiejszego sposobu na wyśmiewanie się z zachowania, jeśli twoja klasa pozostaje w ten sposób. Jednak jeśli chcesz zmienić swój projekt i uczynić obie metody niestatycznymi. Prawidłowym sposobem użycia "kiedy" jest zastosowanie sprawdzenia na wyśmiewanym obiekcie. Na przykład:

BasketHelper basketHelper = mock(BasketHelper.class); 
    when(basketHelper.getAction(request)).thenReturn(0); 
    when(basketHelper.getActionProduct(site, request)).thenReturn(product); 

Ale znowu, to tylko praca, jeśli ponownie zaprojektowany getAction i getProduct metodę swojej klasy, aby mieć charakteru statycznego.

Pamiętam, że istnieją pewne inne ramy testowe, które wspierają szyderstwo metodą statyczną.

+2

Myślę, że PowerMock pozwala na kpiny z metod statycznych. Może powinienem zajrzeć do tego. Dzięki –

+0

Wygląda na to, że :-) Powodzenia z tym. – KKKCoder

+0

Możesz zajrzeć do PowerMocka. Lub możesz zreorganizować swój kod, aby uniknąć użycia metod statycznych. Poleciłbym to drugie. –

1

Możesz użyć PowerMock. Najpierw utworzyć mock klasy, na którym jest wywoływanie metod statycznych -

mockStatic(BasketHelper.class); 

Następnie zdefiniować odcinki -

when(BasketHelper.getAction(request)).thenReturn(0); 
when(BasketHelper.getActionProduct(site, request)).thenReturn(product); 
0

natknąłem tego wątku, starając się rozwiązać ten sam problem w moich testów.

W przypadku, gdy inni widzą ten problem i kończą tutaj ... W moim przypadku było to spowodowane brakiem adnotacji @PrepareForTest dla klasy wsparcia.

Powiązane problemy