这是我的类层次结构
abstract Class A
{
int i = 0;
protected init (String param1, String param2)
{
//do lots of common things based on param1, param2 and save data in i
}
}
然后有3-4个类实现A,即
Class B extends A
{
public B ()
{
super ();
}
public void performSomeAction ()
{
init (param1_specific_to_class_B, param2_specific_to_class_B); //calling parent class method
//do rest of teh random things
}
}
现在,我正试图为类a编写一个JUnit测试。基本上,我想测试init
方法所做的一切是否准确。我试过这个
Class clas = A.class;
B b = new B();
Method A_init;
A_init = clas.getDeclaredMethod("init", String.class, String.class);
A_init.invoke(b, param1_specific_to_class_B, param2_specific_to_class_B);
但它不起作用,我得到以下异常
java.lang.IllegalAccessException: Class test.package.subpackage.ATest can not access a member of class package.subpackage.A with modifiers "protected"
at sun.reflect.Reflection.ensureMemberAccess(Reflection.java:65)
at java.lang.reflect.Method.invoke(Method.java:578)
at test.package.subpackage.ATest.initTest(ATest.java:49)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:585)
您可以将测试类与要测试的类放在同一个包中。因此,测试类将可以访问受保护的方法。
另一个更优雅的选择是使受保护的方法可访问:
A_init = clas.getDeclaredMethod("init", String.class, String.class);
A_init.setAccessible(true);
A_init.invoke(b, param1_specific_to_class_B, param2_specific_to_class_B);
希望能有所帮助。
protected
成员对于另一个包中的类是不可见的,除非它是前者的子类。
但是,在您的应用程序中,类test.package.subpackage.ATest
正试图从package.subpackage
中的另一个类访问受保护的方法,这会导致访问冲突。
尝试将ATest
类放置在一个位置,使A
和ATest
都属于同一个包。
或者,在TestClass中创建一个子类a,并通过公共方法公开受保护的方法:
public class TestClass extends TestCase(){
// ...
private class AChild extends A{
public exposeInit (String param1, String param2){
super.init(param1, param2);
}
}
}
现在您可以通过测试类AChild的init来测试类A的init。
我也遇到过类似的问题,但我们通过将设计改为构图而不是继承来解决这个问题。
也许我遗漏了一些东西,但是,由于B没有覆盖A.init()(至少从我所看到的),你可以直接使用
B b = new B()
b.init(param1_specific_to_class_B, param2_specific_to_class_B)
如果B正在覆盖init(),则
- 把所有东西都放在同一个包裹里(就像其他人贴的那样)
- 如果不可能或不希望更改包,则可能需要向B添加一个调用
super.init()
的特殊方法。我将其命名为类似callSuperInitForUnitTests()
的名称,并在注释中明确表示,这是单元测试的一种变通方法