Tak, jest to możliwe. Załóżmy, że masz ciężko przewodowy klasę, ewentualnie ściągam coś z bazy danych, a chcesz wyśmiewać go poprzez aspekcie:
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 + "]";
}
}
to istnieje niewiele aplikacji kierowca przy użyciu tej samej klasy (a nie interfejsu) :
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());
}
}
wyjście jest w następujący sposób:
HardWired [id=999, name=My object]
Fetching values from database
11
teraz zdefiniować swoją pochodzącą mock klasy, które powinny zastąpić oryginalny dla celów testowych:
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();
}
}
I wreszcie zdefiniować aspekt z prostego punktu przekroju i radę zastąpić oryginalną wartość podczas każdego wywołania konstruktora:
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);
}
}
zmian wyjścia jak życzenia:
Mocked: HardWired [id=999, name=My object]
Mocking database values
22
Robisz które raz na klasę i konstruktora i są w porządku. Aby uogólnić podejście, potrzebne są właściwości joinpoint i, w zależności od tego, jak daleko się posuniesz, może refleksja, ale tutaj jest całkiem prosta. Cieszyć się!
To bardzo szczegółowa odpowiedź, która wydaje się być dokładnie tym, czego szukam. Dzięki! –
Nie tak szybko! Zapomniałem wspomnieć, że aby zastosować to do biblioteki trzeciej strony, musisz wplatać to w kod biblioteki, albo przez LTW albo przez tkanie klas binarnych i zastępowanie biblioteki przez JAR zastępczy. Ta pierwsza jest bardziej dynamiczna, łatwiejsza do wykonania, jeśli żaden menedżer bezpieczeństwa i elementy podpisywania nie powstrzymają od zastąpienia oryginalnego pliku JAR. ;-) – kriegaex
Muszę się przyjrzeć i zobaczyć, co działa najlepiej. W czasie testu mam pełną kontrolę nad hostią JVM i jej środowiskiem. –