2013-08-20 12 views
13

Sto lavorando un po 'su un codice ereditato. Ho scritto un test che dovrebbe prendere NullPointerException (poiché sta cercando di chiamare un metodo da oggetto null)Mockito quando(). ThenReturn chiama il metodo inutilmente

@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); 

} 

relativi metodi e variabili:

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; 
} 

Il risultato jUnit della corsa il test è un fallimento con l'analisi dello stack di:

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# 

faccio a interpretano male come quando thenReturn dovrebbe funzionare lui(). ri? Voglio solo getAction per restituire 0 e getActionProduct per restituire null ogni volta che viene chiamato. Chiaramente getParameter() viene chiamato e non so perché esattamente.

+0

Puoi mostrare 'getProduct()'? –

+0

In altre notizie .... Posso capire perché scrivere questo tipo di test per replicare un problema. Comunque, il vero test qui dovrebbe essere quello di verificare che se il '' '' product'''' è null il metodo '' '' requireX''' non viene chiamato. A meno che il tuo codice ereditato non stia usando il npe per controllare il flusso del codice?Nel qual caso - strappalo anche tu. – OceanLife

+0

Penso che tu abbia ragione. cambiare la condizione nel metodo requireX è probabilmente una buona idea. –

risposta

13

Mockito non può simulare il metodo statico. Il tuo assegno quando non è valido:

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

Questo è un altro motivo per cui vogliamo ridurre l'uso del metodo statico come è difficile prendere in giro.

Non esiste un modo più semplice per prendere in giro il comportamento se la tua classe rimane così. Tuttavia, se si desidera modificare la progettazione e rendere entrambi i metodi non statici. Il modo corretto di usare "quando" è applicare il controllo sull'oggetto deriso. Per esempio:

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

Ma ancora una volta, questa operazione solo lavoro se si ri-progettato il metodo getAction e EsprProdotto della vostra classe di essere non statici.

Ricordo che esistono altri framework di test che supportano il metodo statico di simulazione.

+2

Penso che PowerMock permetta di prendere in giro metodi statici. Forse dovrei esaminarlo. Grazie –

+0

Sembra che sia :-) Buona fortuna con esso. – KKKCoder

+0

Si potrebbe guardare in PowerMock. Oppure puoi refactoring il codice per evitare l'uso di metodi statici. Consiglierei quest'ultimo. –

1

È possibile utilizzare PowerMock. Per prima cosa creare finta della classe su cui si sta chiamando metodi statici -

mockStatic(BasketHelper.class); 

Poi definire il vostro stub -

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

Questo può aiutare gli altri che usano le annotazioni. Se si utilizzano annotazioni, potrebbe essere necessario utilizzare @Mock anziché @InjectMocks. Perché @InjectMocks funziona come @Spy e @Mock insieme. E @Spy tiene traccia dei metodi eseguiti di recente e potresti ritenere che i dati errati vengano restituiti/sommersi. Controllare questi due:

https://groups.google.com/forum/?fromgroups#!topic/mockito/9WUvkhZUy90

http://code.google.com/p/mockito/issues/detail?id=127

0

mi sono imbattuto in questa discussione durante il tentativo di risolvere lo stesso problema nel mio test.

Nel caso in cui altri vedono questo problema e finiscono qui ... Nel mio caso è stato causato dal non utilizzare l'annotazione @PrepareForTest per la classe di supporto.

Problemi correlati