如何使用JUnit测试具有内部私有方法、字段或嵌套类的类?
仅仅为了能够运行测试而更改方法的访问修饰符似乎是不好的。
如何使用JUnit测试具有内部私有方法、字段或嵌套类的类?
仅仅为了能够运行测试而更改方法的访问修饰符似乎是不好的。
当前回答
私有方法被公共方法使用。否则,它们就是死代码。这就是为什么要测试公共方法,断言公共方法的预期结果,从而断言它使用的私有方法。
在公共方法上运行单元测试之前,应该通过调试来测试私有方法。
也可以使用测试驱动开发来调试它们,调试单元测试,直到满足所有断言。
我个人认为最好使用TDD创建类;创建公共方法存根,然后使用预先定义的所有断言生成单元测试,这样在编写代码之前就可以确定方法的预期结果。这样,就不会走上使单元测试断言符合结果的错误道路。然后,当所有单元测试通过时,您的类是健壮的并满足要求。
其他回答
如果您只使用Mockito:
您可以将私有方法视为正在测试的公共方法的一部分。您可以确保在测试公共方法时覆盖私有方法中的所有情况。
假设您是一个仅限Mockito的用户(不允许或不想使用PowerMock或反射或任何此类工具),并且不想更改正在测试的现有代码或库,这可能是最好的方法。
如果选择这种方式,唯一需要处理的就是在私有方法中本地声明的变量(用户定义的对象)。如果私有方法依赖于本地声明的变量对象及其方法,请确保将这些用户定义的对象全局声明为私有对象,而不是本地声明的对象。您可以在本地实例化这些对象。
这允许您模拟这些对象并将它们注入回测试对象。你也可以模仿(使用when/then)他们的方法。
这将允许您在测试公共方法时无错误地测试私有方法。
优势
代码覆盖范围能够测试完整的私有方法。
缺点
对象的作用域如果您不希望对象公开给同一类中的其他方法,这可能不是您的方式。当在不同的公共方法和/或在同一方法中多次调用时,您可能会多次测试私有方法。
如果您想测试不能更改代码的遗留应用程序的私有方法,Java的一个选项是jMockit,它将允许您创建对象的模拟,即使它们对类是私有的。
在C++中:在包含包含要测试的私有函数的类头之前。
使用此代码:
#define private public
#define protected public
如果您确实需要直接测试私有方法/类等,那么可以使用其他答案中已经提到的反射。然而,如果说到这一点,我宁愿使用框架提供的实用程序类,而不是直接处理反射。例如,对于Java,我们有:
Spring框架中的ReflectionUtilsJUnit中的ReflectionUtils
关于如何使用它们,你可以在网上找到很多文章。我特别喜欢这个:
org.springframework.util.ReflectionUtils的Java代码示例
在您的课堂上:
namespace my_namespace {
#ifdef UNIT_TEST
class test_class;
#endif
class my_class {
public:
#ifdef UNIT_TEST
friend class test_class;
#endif
private:
void fun() { cout << "I am private" << endl; }
}
}
在单元测试类中:
#ifndef UNIT_TEST
#define UNIT_TEST
#endif
#include "my_class.h"
class my_namespace::test_class {
public:
void fun() { my_obj.fun(); }
private:
my_class my_obj;
}
void my_unit_test() {
test_class test_obj;
test_obj.fun(); // here you accessed the private function ;)
}