是的,這是可能的。讓我們假設你有一個硬連線級,可能從數據庫中獲取的東西,並希望通過一個方面來嘲笑它:
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
你做每個類和構造函數一次,並且都很好。爲了推廣該方法,您需要連接點屬性,並根據您想要走多遠,也許反射,但這裏這是非常簡單的。請享用!
這是一個非常詳細的答案,這似乎正是我正在尋找的。謝謝! – 2013-05-03 12:02:09
不是那麼快!我忘了提及,爲了將其應用於第三方庫,您需要通過LTW或編織二進制類並將替換庫替換爲替換JAR來將其編譯到庫的代碼中。前者更具動態性,後者更容易做到,如果沒有安全管理者和簽名的東西阻止你取代原來的JAR。 ;-) – kriegaex 2013-05-03 12:05:03
我會看看,看看最好的。在測試時,我可以完全控制託管的JVM及其環境。 – 2013-05-03 12:08:30