Подтвердить что ты не робот

Mockito when(). ThenReturn вызывает ненужный метод

Я немного работаю над унаследованным кодом. Я написал тест, который должен поймать NullPointerException (поскольку он пытается вызвать метод из нулевого объекта)

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

}

Соответствующие методы и переменные:

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

Результат jUnit при запуске теста является ошибкой с трассировкой стека:

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#

Я неправильно истолковываю, как if(). thenReturn должен работать здесь? Я просто хочу, чтобы getAction возвращал 0 и getActionProduct, чтобы возвращать null всякий раз, когда он вызывается. Очевидно, что getParameter() вызывается, и я точно не знаю, почему именно.

4b9b3361

Ответ 1

Мокито не может издеваться над статическим методом. Если проверка недействительна:

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

Это еще одна причина, по которой мы хотим уменьшить использование статического метода, поскольку его сложно издеваться.

Нет более простого способа издеваться над поведением, если ваш класс останется таким. Однако, если вы хотите изменить свой дизайн и сделать оба метода нестатичными. Правильный способ использования "когда" - применить проверку на издеваемом объекте. Например:

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

Но еще раз, это работает, только если вы переработали свой метод getAction класса и getProduct, чтобы быть НЕСТАТИЧЕСКИМ.

Я помню, что есть еще одна среда тестирования, которая поддерживает насмешливый статический метод.

Ответ 2

Вы можете использовать PowerMock. Сначала создайте mock класса, на который вы вызываете статические методы -

mockStatic(BasketHelper.class);

Затем определите свои заглушки -

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

Ответ 3

Это может помочь другим, кто использует аннотации. Если вы используете аннотации, возможно, вам нужно использовать @Mock вместо @InjectMocks. Поскольку @InjectMocks работает как @Spy и @Mock вместе. И @Spy отслеживает недавно выполненные методы, и вы можете почувствовать, что неверные данные возвращаются/подсловы. Проверьте эти два параметра:

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

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

Ответ 4

Я столкнулся с этим потоком, пытаясь исправить ту же проблему в своих тестах.

Если другие видят эту проблему и заканчиваются здесь... В моем случае это было вызвано не использованием аннотации @PrepareForTest для класса поддержки.