java - Mockito when().thenReturn 不必要地调用该方法

标签 java testing junit mockito

我正在研究继承的代码。 我编写了一个应该捕获 NullPointerException 的测试(因为它试图从 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);

}

相关方法和变量:

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#

我是否误解了 when().thenReturn 在这里应该如何工作?我只想让 getAction 返回 0 并让 getActionProduct 在调用时返回 null。很明显 getParameter() 被调用了,我不知道为什么。

最佳答案

Mockito 不能模拟静态方法。您的 when 检查无效:

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

这也是我们希望减少使用静态方法的另一个原因,因为它很难模拟。

如果您的类(class)保持这样,没有更简单的方法来模拟行为。但是,如果您想更改设计并使这两种方法都非静态。使用“when”的正确方法是对模拟对象应用检查。例如:

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

但是再说一次,这只有在您将类的 getAction 和 getProduct 方法重新设计为非静态方法时才有效。

我记得有一些其他的测试框架确实支持模拟静态方法。

关于java - Mockito when().thenReturn 不必要地调用该方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18340007/

相关文章:

java - 无法使用Servlet从数据库检索数据并在JSP中显示

java - 使用流式 api 遍历字段而不是遍历对象

java - 单元测试应该使用日志记录吗?

javascript - 如何对 Firefox 57 WebExtensions 进行单元测试?

java - 没有静态方法的junit测试

c# - 将结果添加到 TestCaseSource

java - 使用线程进行 JUnit 测试 - 测试执行器行为

java - 在jsp页面中显示特殊字符

java - 从作为参数传递的数组创建测试用例名称(使用 JUnitParams)

java - Junit 测试 - 没有我能看到的错误?