JUnit测试:调用父类保护的方法



这是我的类层次结构

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类放置在一个位置,使AATest都属于同一个包。

或者,在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(),则

  1. 把所有东西都放在同一个包裹里(就像其他人贴的那样)
  2. 如果不可能或不希望更改包,则可能需要向B添加一个调用super.init()的特殊方法。我将其命名为类似callSuperInitForUnitTests()的名称,并在注释中明确表示,这是单元测试的一种变通方法

相关内容

  • 没有找到相关文章