1

这是我的班级层次结构

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)
4

4 回答 4

4

您可以将测试类与被测试类放在同一个包中。所以测试类将可以访问受保护的方法。

另一个更优雅的选择是使受保护的方法可访问:

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);

希望能帮助到你。

于 2013-02-19T23:22:42.730 回答
1

protected一个类的成员对另一个包中的类不可见,除非它是前者的子类。

但是,在您的应用程序中,该类test.package.subpackage.ATest试图从 中的另一个类访问受保护的方法package.subpackage,这会导致访问冲突。

尝试将ATest类放置到一个位置,使两者都A属于ATest同一个包。

于 2013-02-19T23:12:28.680 回答
1

或者,在您的 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。

我有类似的问题,但我们通过将设计改为组合而不是继承来解决它。

于 2014-04-02T08:08:04.743 回答
0

也许我错过了一些东西,但是,因为 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()并在评论中明确说明这是单元测试的一种解决方法。
于 2013-02-19T23:23:17.490 回答