Junit私有方法测试



我正在尝试编写一个实用程序方法,以便在测试中的类中轻松调用私有方法。我有这个:

private Object callPrivateMethod(String methodName, Object subject, Object... parameters) {
    try {
        Class<?>[] paramTypes = new Class<?>[parameters.length];
        for (int index=0; index<parameters.length; index++) {
            paramTypes[index] = parameters[index].getClass();
        }
        Method method = subject.getClass().getDeclaredMethod(methodName, paramTypes);
        method.setAccessible(true);
        return method.invoke(subject, parameters);
    } catch (Exception e) {
        e.printStackTrace();
        fail(e.getMessage());
        return null;
    }
}

但当我尝试使用以下代码调用它时:

List<Session> sessions = new ArrayList<Session>();
// fill the array list
String sessionLines = (String) callPrivateMethod("getSessionsForEmail", emailSender, sessions);

我得到这个例外:

java.lang.NoSuchMethodException: staffing.server.email.EmailSender.getSessionsForEmail(java.util.ArrayList)

EmailSender(测试中的类(中的方法签名如下所示:

private String getSessionsForEmail(List<Session> sessions) {
   //do stuff
}

试图弄清楚为什么反射找不到方法。List和ArrayList不是完全相同的类,这有什么关系?如果是,我该怎么办?

最好不要直接测试私有方法。通过公共和/或受保护的方法访问它们,我们正在测试系统在生产中的行为。这种方法还允许您通过公共/受保护的方法发送所有数据组合来管理测试覆盖率。

可以通过在测试源文件夹中使用相同的包名称来测试受保护的方法。

如果必须测试私有方法,那么您可以使用Powermock之类的嘲讽工具,最好是Mockito,而不是自己进行反射。这两个工具都与JUnit有很好的集成。这是一条陡峭的学习曲线,但值得投资。这里有更多详细信息:使用mockito 测试私有方法

您的代码试图找到一个以ArrayList(sessions的具体类(为参数的方法。但是您的方法不将ArrayList作为自变量。它以List作为自变量。

除了参数值之外,还需要传递方法的参数类型。

或者,您可以重构代码,使方法受到保护或包受到保护,或者将其作为公共方法放在另一个协作类中。

当前的推理认为不应该测试私有方法。它们要么是特定于实现的,应该通过调用它们的方法进行测试。或者,它们应该被提取到自己的类中,并通过该类进行测试。我们的想法是,如果你的私有方法做得太多,需要单独测试,那么你的类做得太少,应该被分解。

这样看待它有很多好处,尤其是不用破解类来测试它。

如果你真的想在自己的实现中取得成功,我觉得看看Java中的类型擦除可能会很有用。

否则,正如Akber Choudhry所指出的,Mockito附带了一个很好的实用程序包,名为org.powermock.reflect.Whitebox。我肯定会使用它。

最后,我不会说永远不要测试私有方法,但如果你打算测试它们,请三思。保持基于反思的方法不是最简单的事情,而且很容易出错。

这可以通过JUnit4+Mockito来完成。

要模拟私有方法,我们可以简单地使用mockit。去胶囊包装:

Deencapsulation.invoke(myService, "methodName", arg1, arg2);

我们可以根据需要用Mockito.anyString((等替换参数。

相关内容

  • 没有找到相关文章

最新更新