如何使用JUnit测试具有内部私有方法、字段或嵌套类的类?
仅仅为了能够运行测试而更改方法的访问修饰符似乎是不好的。
如何使用JUnit测试具有内部私有方法、字段或嵌套类的类?
仅仅为了能够运行测试而更改方法的访问修饰符似乎是不好的。
当前回答
我只测试公共接口,但众所周知,我会保护特定的私有方法,因此我可以完全模拟它们,或者添加特定于单元测试目的的额外步骤。一般情况下,挂接我可以从单元测试中设置的标志,以使某些方法故意导致异常,从而能够测试故障路径;异常触发代码仅在受保护方法的重写实现中的测试路径中。
不过,我尽量不需要这样做,我总是记录下确切的原因,以避免混淆。
其他回答
如果您想测试不能更改代码的遗留应用程序的私有方法,Java的一个选项是jMockit,它将允许您创建对象的模拟,即使它们对类是私有的。
正如上面许多人所建议的,一个好的方法是通过公共接口测试它们。
如果您这样做,最好使用代码覆盖工具(如EMMA)来查看您的私有方法是否确实在测试中执行。
如果您正在使用JUnit,请查看JUnit插件。它能够忽略Java安全模型并访问私有方法和属性。
我最近遇到了这个问题,并编写了一个名为Picklock的小工具,它避免了显式使用Java反射API的问题,两个示例:
通过Java反射调用方法,例如private void方法(String s)
Method method = targetClass.getDeclaredMethod("method", String.class);
method.setAccessible(true);
return method.invoke(targetObject, "mystring");
通过Picklock调用方法,例如private void方法(String s)
interface Accessible {
void method(String s);
}
...
Accessible a = ObjectAccess.unlock(targetObject).features(Accessible.class);
a.method("mystring");
设置字段,例如私有BigInteger金额;-通过Java反射
Field field = targetClass.getDeclaredField("amount");
field.setAccessible(true);
field.set(object, BigInteger.valueOf(42));
设置字段,例如私有BigInteger金额;-由Picklock提供
interface Accessible {
void setAmount(BigInteger amount);
}
...
Accessible a = ObjectAccess.unlock(targetObject).features(Accessible.class);
a.setAmount(BigInteger.valueOf(42));
如果您的测试类与应该测试的类在同一个包中呢?
当然,在另一个目录中,源代码使用src&classes,测试类使用test/src和test/classes。让类和测试/类位于类路径中。