2013-05-03 48 views
7

我在看AspectJ,看看我們是否可以在我們的測試套件中使用它。AspectJ可以在第三方庫代碼中用「new SubclassOfX」替換「new X」嗎?

我們有一個相當大的第三方Java通信庫硬連線使用自己的類(它沒有實現任何接口),這反過來意味着我們需要物理後端存在並正確配置爲能夠運行測試。

我正在查看我們的選項以消除此限制。一種可能性是創建麻煩類的子類,然後在加載第三方庫時,請求AspectJ簡單地將「new X」替換爲「new OurSubclassOfX」,但我是AspectJ的新手,並且從我簡要介紹的文檔不是典型的用例。

Can AspectJ能做到這一點嗎?配置代碼段是什麼?

回答

9

是的,這是可能的。讓我們假設你有一個硬連線級,可能從數據庫中獲取的東西,並希望通過一個方面來嘲笑它:

package de.scrum_master.aop.app; 

public class HardWired { 
    private int id; 
    private String name; 

    public HardWired(int id, String name) { 
     this.id = id; 
     this.name = name; 
    } 

    public void doSomething() { 
     System.out.println("Fetching values from database"); 
    } 

    public int getSomething() { 
     return 11; 
    } 

    @Override 
    public String toString() { 
     return "HardWired [id=" + id + ", name=" + name + "]"; 
    } 
} 

再有就是使用非常類一個小驅動程序(而不是一個接口) :

package de.scrum_master.aop.app; 

public class Application { 
    public static void main(String[] args) { 
     HardWired hw = new HardWired(999, "My object"); 
     System.out.println(hw); 
     hw.doSomething(); 
     System.out.println(hw.getSomething()); 
    } 
} 

輸出如下:

HardWired [id=999, name=My object] 
Fetching values from database 
11 

現在您可以在定義派生模擬類應取代原有的用於測試目的:

package de.scrum_master.aop.mock; 

import de.scrum_master.aop.app.HardWired; 

public class HardWiredMock extends HardWired { 
    public HardWiredMock(int id, String name) { 
     super(id, name); 
    } 

    @Override 
    public void doSomething() { 
     System.out.println("Mocking database values"); 
    } 

    @Override 
    public int getSomething() { 
     return 22; 
    } 

    @Override 
    public String toString() { 
     return "Mocked: " + super.toString(); 
    } 
} 

最後你定義一個簡單的切入點和建議一個方面,每個構造函數調用中替換原來的值:

package de.scrum_master.aop.aspect; 

import de.scrum_master.aop.app.HardWired; 
import de.scrum_master.aop.mock.HardWiredMock; 


public aspect MockInjector { 
    HardWired around(int p1, String p2) : call(HardWired.new(int, String)) && args(p1, p2) { 
     return new HardWiredMock(p1, p2); 
    } 
} 

根據需要輸出的變化:

Mocked: HardWired [id=999, name=My object] 
Mocking database values 
22 

你做每個類和構造函數一次,並且都很好。爲了推廣該方法,您需要連接點屬性,並根據您想要走多遠,也許反射,但這裏這是非常簡單的。請享用!

+0

這是一個非常詳細的答案,這似乎正是我正在尋找的。謝謝! – 2013-05-03 12:02:09

+0

不是那麼快!我忘了提及,爲了將其應用於第三方庫,您需要通過LTW或編織二進制類並將替換庫替換爲替換JAR來將其編譯到庫的代碼中。前者更具動態性,後者更容易做到,如果沒有安全管理者和簽名的東西阻止你取代原來的JAR。 ;-) – kriegaex 2013-05-03 12:05:03

+0

我會看看,看看最好的。在測試時,我可以完全控制託管的JVM及其環境。 – 2013-05-03 12:08:30

相關問題