2013-02-27 158 views
2

我加入的測試用例來測試套件如下:泛型方法,可以構建泛型類型

for(String methodName : getPublicDeclaredMethods(TestA.class)) 
{ 
    this.addTest((new TestA(methodName))); 
} 

for(String methodName : getPublicDeclaredMethods(TestB.class)) 
{ 
    this.addTest((new TestB(methodName))); 
} 

這相當於這樣做:

this.addTest((new TestA("TEST_METHOD_1"))); 
this.addTest((new TestA("TEST_METHOD_2"))); 
this.addTest((new TestB("TEST_METHOD_1"))); 
this.addTest((new TestB("TEST_METHOD_3"))); // woops I forgot TEST_METHOD_2 

我卡與這個怪異的測試框架,其中方法名稱通過構造以字符串形式提供。

我上面的代碼保證我添加了在特定類中定義的所有測試用例。不過,我想有這看起來是這樣的,而不是一個方法:

void <T> addTestCasesFromClass() 
{ 
    for(String methodName : getPublicDeclaredMethods(T.class)) 
    { 
     this.addTest((new T(methodName))); 
    } 
} 

但我不知道這是如何在Java中完成。它甚至有可能嗎? TestA和TestB是從Test類派生的。

回答

1

這裏泛型沒用,因爲你不能做類似new T的東西。但你可以通過更多的思考來做到這一點。假設你傳遞給這個方法的所有類都有一個構造函數,它只接受一個String參數。

void addTestCasesFromClass(Class<?> clz) 
{ 
    for(String methodName : getPublicDeclaredMethods(clz)) 
    { 
     this.addTest(clz.getConstructor(String.class).newInstance(methodName)); 
    } 
} 

的調用將然後是這個樣子

addTestCasesFromClass(TestA.class); 
addTestCasesFromClass(TestB.class); 

如果您addTest方法只接受某一基類對象(讓它成爲TestBase),然後更改的clzClass<? extends TestBase> clz泛型參數。

+0

上午我說得對,這種方法拋出:IllegalArgumentException - ,拋出:SecurityException,InstantiationException,IllegalAccessException,的InvocationTargetException,NoSuchMethodException? – Baz 2013-02-27 13:11:27

+0

聽起來沒錯,我出於簡潔的原因離開了異常處理。另外我不知道如何處理異常(如果'clz'沒有提供接受字符串的可訪問構造函數)。 – Stephan 2013-02-27 13:49:51

1

當您只有對泛型類型的引用時,您無法實例化。 泛型只在編譯時可用,因此在運行時不能使用它們。 這意味着您將需要對實際的類Class的引用並通過反射來實例化它。

Class<?> clazz = ... 
Object instance = clazz.newInstance(); 

它鼓勵使用getConstructor雖然代替。

一個很好的例子是java中的List.toArray方法,它需要你傳遞數組的一個實例,以便它能夠實際引用類,因爲泛型在運行時不可用。

1

您可以使用反射來查找接受字符串參數的傳遞類的構造函數。然後使用您檢索的方法名稱實例化您的類。

public <T> void addTestClassesFromClass(T item){ 
    try { 
     Constructor<?> constructor = item.getClass().getConstructor(String.class); 
     for(String methodName : getPublicDeclaredMethods(item.getClass())){ 
      this.addTest((constructor.newInstance(methodName))); 
     } 
    } catch (Exception e) { 
     System.out.println("Oh crap!"); 
    } 
} 
0

這裏是我的嘗試:

public void addTestCasesFromClass(Class<? extends Test> c) throws IllegalArgumentException, SecurityException, InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException 
{ 
    for(String methodName : getPublicDeclaredMethods(c)) 
    { 
     this.addTest((c.getDeclaredConstructor(String.class).newInstance(methodName))); 
    } 
}