2013-02-19 38 views
1

這裏是我的類層次結構的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 
    } 
} 

再就是它實現了即

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 
    } 
} 

現在3-4班,我試圖寫一個JUnit測試類A.基本上我想測試什麼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

您可以將您的測試類放在與正在測試的類相同的包中。所以測試類將有權訪問受保護的方法。

另一種選擇,更優雅一點,是使訪問受保護的方法:

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

希望它能幫助。

+0

將類移動到該包不是一個選項,因爲我們有2個不同的包heirarchy(項目類在src文件夾中,測試在測試foldeR中)。感謝'setAccessible(true)'。多數民衆贊成我正在尋找 – 2013-02-19 23:29:30

+0

正如Maven項目所發生的,你有一個src和一個測試文件夾,但不同的文件夾不一定意味着不同的包。 – Lucas 2013-02-19 23:48:53

1

protected成員不visible一類,除非是前者的一個子類。

但是,在您的應用程序中,類test.package.subpackage.ATest正嘗試從package.subpackage中的另一個類訪問受保護的方法,這會導致訪問衝突。

嘗試將ATest類放置到某個位置,以使AATest屬於同一個包。

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(),並在評論中明確指出這是單元測試的解決方法。
+0

對不起,這是一個錯字。 B擴展了A.我修復了代碼 – 2013-02-19 23:30:33

+0

我知道B擴展了A.重點是如果你想測試A.init,並且B不覆蓋A.init,你可以調用b.init()。否則,這些是一些可能的解決方法:將文件移動到相同的軟件包,設置爲可訪問,或通過中間件調用A.init。 – user949300 2013-02-19 23:40:53

1

或者在你的TestClass創建A的一個子類,並通過一個公共方法暴露保護法(S):

public class TestClass extends TestCase(){ 

    // ... 

    private class AChild extends A{ 
     public exposeInit (String param1, String param2){ 
     super.init(param1, param2); 
     } 
    } 
} 

現在你可以通過測試類AChild的初始化測試發起A類。

我有類似的問題,但我們通過改變設計而不是繼承來解決它。