2011-02-24 58 views
0

作爲一個更大的項目的一部分,我試圖實現一些我不太確定的事情,所以我非常希望看到有沒有人有任何建議!對任意加載的類運行JUnit測試

整個系統:
作爲一個整體,我的系統應該能夠提供一個JUnit測試類,符合一些提供接口。然後給出的類不會實現這個接口,但需要檢查它們是否能夠(如果它們實現了所有必要的方法)。如果是這樣,那麼應該進行一些轉換,以便JUnit測試類可以針對它運行。

到目前爲止,我已經實現了:
- 運行JUnit測試用例並返回結果,使用JUnitCore

一個包 - 加載給出的路徑和名稱,使用的URLClassLoader
其他類的包

問題:
1.首先,如何針對在測試設計爲匹配接口時實現接口的類運行JUnit測試?我(在運行時)如何規定接口測試的實例是加載的類?

  1. 是否有可能再擴展此,例如,我可以ⅰ)驗證它確實匹配的接口(I假設使用反射來檢查對應的方法?),然後ⅱ)修改類,使得它可以使用JUnit測試類進行測試?

感謝您的任何建議,可能有助於解決部分問題。我很欣賞我的描述可能缺乏,所以如果您有任何額外的信息可以幫助您提供任何答案,請發表評論!

+0

你在這裏試圖解決的根本問題是什麼? – 2011-02-24 21:30:03

回答

1

你可以用反射API做你想做的一切。聽起來你應該從the tutorial開始,然後回到這裏來回答特定的問題。給定一個Class對象,你可以檢查它是否實現了給定的接口,創建它的一個實例,然後像對待其他類一樣對待它。

編輯:我不認爲我是從你的問題,但在這種情況下,你要尋找的反射API的Proxy一部分。

+0

謝謝,我知道這是事情的正確方向。然而,我將如何去了解我所描述的擴展版本,以便我需要i)查看類是否具有實現該接口的所有方法,ii)如果是這樣,請將它看作是測試用例。 另外,當測試只與接口相匹配時,如何測試與JUnit中的接口相匹配的類? – obfuscation 2011-02-24 21:32:04

1

我怎麼能運行JUnit測試對 一類確實實現了 接口時,測試的目的是 匹配接口

既然你有這個類可以使用isAssignableFrom方法由類這樣

Class loadedJunitClass = clazz; 
MyInterface impl = null; 
if(MyInterface.class.isAssignableFrom(loadedJunitClass)){ 
    impl = (MyInterface) loadedJunitClass.newInstance(); 
} 

對於第二個問題,你可以檢查每一個方法,看看1.如果存在一個方法,用同樣的方法提供吶me定義在接口中,2.如果方法返回類型與接口相同,並且3.如果方法參數類型和長度相同。當然,2和3可能會很棘手。

在這一點上,我只是創建該接口(匿名或私人類)的一個實例,創建該匹配類的newInstance。並通過接口方法內的反射調用方法。

現在這就是你如何用反射來完成它。我不會提醒你反思,因爲你可以想象:)

1

對於你的問題的第一部分;如果您要爲要測試的類加載Class實例,則可以使用newInstance()(如果它具有默認構造函數)或使用getConstructor方法(如果需要傳遞參數)構造一個實例。你應該能夠從類加載器中獲得這個Class實例。

第二部分。您應該可以通過getMethods()(再次在Class實例上)檢查公共方法,然後通過返回的數組查看所需的方法。 Method類中有一些方法將返回有關參數,例外和返回類型的信息,以驗證它們是您需要的。

但是,我非常肯定,不可能在運行時修改類以添加接口。通過修改字節碼可能是可能的,但我不知道這一點。

另一種方法是編寫測試以通過反射調用所有方法,然後不管對象的類型是什麼,只要它具有正確的方法(您已經檢查過)。

1

如果您希望在運行時實現給定接口的任意類(如果其公共API與接口匹配),那麼Java中有幾個選項。創建java.lang.Proxy橋接目標類,揭示YourInterface是最簡單的方法。

YourInterface i = (YourInterface) Proxy.newProxyInstance(
     this.getClass().getClassLoader(), 
     new Class[]{YourInterface.class}, 
     new InvocationHandler() { 

    @Override 
    public Object invoke(Object o, Method method, Object[] objects) throws Throwable { 
     //run method on your target class here using reflection 
    } 

}); 

您還可以在AspectJ中使用mixins,或者使用CGLIB在目標類中創建子類並在運行時添加接口。但代理方式並不是實施的核心。