首页 > 解决方案 > 无法对 Java 代码使用 Mockito 或 PowerMockito 的反射进行单元测试

问题描述

我正在尝试编写一个单元测试来测试这段代码,但是我遇到了本地类 java.lang.Class 的 Mockito/Powermockito 限制,如此所述。

我怎么能测试这个:

Method[] serverStatusMethods = serverStatus.getClass().getMethods();
    for (Method serverStatusMethod : serverStatusMethods) {
        if (serverStatusMethod.getName().equalsIgnoreCase("get" + field)) {
            serverStatusMethod.setAccessible(true);
            try {
                Number value = (Number) serverStatusMethod.invoke(serverStatus);
                response = new DataResponse(field + " value", value);
            } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
                Logger.getLogger(StatusServlet.class.getName()).log(Level.SEVERE, null, ex);
                response = new ErrorResponse(HttpStatus.Code.INTERNAL_SERVER_ERROR, ex);
            }
            break;
        }
    }

在测试用例中故意抛出这个异常:

catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
            Logger.getLogger(StatusServlet.class.getName()).log(Level.SEVERE, null, ex);
            response = new ErrorResponse(HttpStatus.Code.INTERNAL_SERVER_ERROR, ex);
}

标签: javaunit-testingreflectionmockitopowermockito

解决方案


每当模拟一个类太困难时,做你所做的:添加另一层抽象。例如,将反射操作提取到一个单独的方法中:

public Number resolveServerStatus(Object serverStatus)
    throws IllegalAccessException, IllegalArgumentException,
        InvocationTargetException {

    Method[] serverStatusMethods = serverStatus.getClass().getMethods();
    for (Method serverStatusMethod : serverStatusMethods) {
        if (serverStatusMethod.getName().equalsIgnoreCase("get" + field)) {
            serverStatusMethod.setAccessible(true);
            return (Number) serverStatusMethod.invoke(serverStatus);
        }
    }
}

现在模拟该resolveServerStatus方法。

如果您遵循单一责任原则,这就是您首先应该做的事情。您的方法有两个职责:解析状态编号并将其转换为DataResponse对象。多重责任使测试该方法变得困难。


推荐阅读