Mockito when().thenReturn calls the method unnecessarily

45,646

Solution 1

Mockito cannot mock static method. Your when check is not valid:

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

That is another reason why we want to reduce the use of static method as it is hard to mock.

There is no easier way to mock the behavior if your class stays like this. However if you want to change your design and make both methods non-static. The correct way of using "when" is to apply the check on mocked object. For example:

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

But once again, this only work if you re-designed your class's getAction and getProduct method to be NON-STATIC.

I remember there are some other testing framework that does support mocking static method.

Solution 2

You can use PowerMock. First create mock of the class on which you are calling static methods -

mockStatic(BasketHelper.class);

Then define your stubs -

when(BasketHelper.getAction(request)).thenReturn(0);
when(BasketHelper.getActionProduct(site, request)).thenReturn(product);
Share:
45,646
Krzysztof Jarzyna
Author by

Krzysztof Jarzyna

Updated on May 30, 2020

Comments

  • Krzysztof Jarzyna
    Krzysztof Jarzyna almost 4 years

    I'm working a bit on an inherited code. I've written a test that is supposed to catch NullPointerException (for it is trying to call a method from null object)

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

    Relevant Methods and Variables:

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

    The jUnit result of running the test is a failure with the stack trace of:

    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#
    

    Do I misinterpret how when().thenReturn is supposed to work here? I just want getAction to return 0 and getActionProduct to return null whenever it's being called. Clearly getParameter() is called and I don't know why exactly.