2013-05-03 10 views
7

Sto guardando AspectJ per vedere se forse possiamo usarlo nella nostra suite di test.AspectJ può sostituire "new X" con "new SubclassOfX" nel codice di libreria di terze parti?

Abbiamo una libreria di comunicazioni Java di terze parti piuttosto grande, cablata per utilizzare le sue classi (che non implementano alcuna interfaccia) che a sua volta significa che abbiamo bisogno di un back-end fisico e configurato correttamente per poter eseguire i test.

Sto osservando le nostre opzioni per rimuovere questa restrizione. Una possibilità sarebbe quella di creare una sottoclasse delle classi fastidiose e quindi chiedere ad AspectJ di sostituire semplicemente "nuova X" con "new OurSubclassOfX" quando si carica la libreria di terze parti, ma io sono nuovo di AspectJ e dalla mia breve rassegna della documentazione questa non è un tipico caso d'uso.

AspectJ può fare questo? Quale sarebbe lo snippet di configurazione?

risposta

9

Sì, questo è possibile. Supponiamo di avere una classe hard-wired, forse andare a prendere qualcosa da un database, e si vuole prendere in giro tramite un aspetto:

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 + "]"; 
    } 
} 

Poi c'è un'applicazione po 'driver utilizzando quella stessa classe (non un'interfaccia) :

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()); 
    } 
} 

l'uscita è la seguente:

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

Ora si definisce la classe finta derivato che dovrebbe sostituire l'originale a scopo di test:

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(); 
    } 
} 

E infine si definisce un aspetto con una semplice pointcut e consigli per sostituire il valore originale durante ogni chiamata del costruttore:

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); 
    } 
} 

L'uscita come desiderato:

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

Fate quello una volta per classe e costruttore e sta bene. Per generalizzare l'approccio avresti bisogno di proprietà joinpoint e, a seconda di quanto lontano vuoi andare, magari di riflessione, ma questo qui è piuttosto semplice. Godere!

+0

Questa è una risposta molto dettagliata, che sembra essere esattamente quello che sto cercando. Grazie! –

+0

Non così veloce! Ho dimenticato di menzionare che per applicarlo su una libreria di terze parti è necessario inserirlo nel codice della lib, sia da LTW che tessendo le classi binarie e sostituendo la lib con un JAR sostitutivo. Il primo è più dinamico, il secondo è più facile da fare se nessun responsabile della sicurezza e materiale per la firma non ti impedisce di sostituire il JAR originale. ;-) – kriegaex

+0

darò un'occhiata e vedrò cosa funziona meglio. Al momento del test, ho il pieno controllo della JVM di hosting e del suo ambiente. –

Problemi correlati