web-dev-qa-db-fra.com

Mockito when (). ThenReturn appelle inutilement la méthode

Je travaille un peu sur un code hérité ... J'ai écrit un test qui est censé intercepter NullPointerException (car il essaie d'appeler une méthode depuis un objet null)

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

}

Méthodes et variables pertinentes:

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

Le résultat de l'exécution du test avec jUnit est un échec avec la trace de pile de:

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#

Dois-je mal interpréter comment quand (). ThenReturn est censé fonctionner ici? Je veux juste que getAction renvoie 0 et que getActionProduct renvoie null à chaque appel. Clairement, getParameter () est appelé et je ne sais pas pourquoi exactement.

15
Krzysztof Jarzyna

Mockito ne peut pas se moquer de la méthode statique. Votre vérification quand n'est pas valide:

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

C'est une autre raison pour laquelle nous voulons réduire l'utilisation de la méthode statique car il est difficile de se moquer.

Il n'y a pas de moyen plus facile de se moquer du comportement si votre classe reste comme ça. Toutefois, si vous souhaitez modifier votre conception et rendre les deux méthodes non statiques. La bonne façon d’utiliser «quand» consiste à appliquer la vérification à l’objet simulé. Par exemple:

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

Mais encore une fois, cela ne fonctionne que si vous avez repensé les méthodes getAction et getProduct de votre classe pour qu'elles soient NON-STATIQUES.

Je me souviens qu'il existe un autre framework de test qui supporte la méthode statique moqueuse.

14
KKKCoder

Vous pouvez utiliser PowerMock. Commencez par créer une maquette de la classe sur laquelle vous appelez des méthodes statiques -

mockStatic(BasketHelper.class);

Puis définissez vos talons -

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

Cela peut aider les autres utilisateurs d’annotations. Si vous utilisez des annotations, vous devrez peut-être utiliser @Mock au lieu de @InjectMocks. Parce que @InjectMocks fonctionne en tant que @Spy et @Mock ensemble. Et @Spy garde la trace des méthodes récemment exécutées et vous pouvez avoir l’impression que des données incorrectes sont renvoyées/sous-lits . Vérifiez ces deux éléments:

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

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

0
dillip pattnaik

J'ai rencontré ce fil en essayant de résoudre le même problème dans mes tests.

Si d’autres voient ce problème et aboutissent ici ... Dans mon cas, cela est dû à l’absence d’annotation @PrepareForTest pour la classe de support.

0
John Dilley