Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
interecepting all calls -- was Re: [aspectj-users] interecepting of all calls and forwarding them, aspect methods and private fields

(Splitting the emails - 1 topic per email, please.)

"Wojciech (Voytek) Dzidek" wrote:
> 
> Question 1:
> 
> Let's say I have two classes: Stopped and StoppedStub. During testing I want all calls to Stopped
> be forwarded to StoppedStub. 

Forwarding can be done with reflection based on the signature available
from thisJoinPoint for method-call join points.  (*shudder*)

But forward to which instance?  A different one for each call?

Aside from forwarding, you can also replace the executing object with 
your mock object.  But when?  Likely on construction or relevant
assignment, to preserve the identity of the mock object across the
relevant invocations.  But since there is no join point for local 
variable assignments, this is sometimes not possible.

There's also the question of maintenance.  What happens if methods 
are added to the component under test, but not the mock?

Below is some code that replaces with a mock for each call.  It assumes
interface I defines the contract supported by both the component
under test and the mock object.

Here's the result:
----------- without the aspect -- same instance for two calls
B@126b249.a()
B@126b249.b()
----------- with the aspect -- different mock for two calls
Mock@182f0db.a()
Mock@192d342.b()
----------- 

I'd be interested to see a code example with advice that replaced 
the object after it was constructed.

Wes

----------- Replace.java

public class Replace {
    public static void main (String[] args) {
        I i = new B();
        i.a();   // two different calls to same instance
        i.b();
    } 
    static void log (String m) { System.out.println(m); }
}

interface I {
    void a();
    void b();
}

class B implements I {
    public void a() { Replace.log(this + ".a()"); }
    public void b() { Replace.log(this + ".b()"); }
}

class Mock implements I {
    public void a() { Replace.log(this + ".a()"); }
    public void b() { Replace.log(this + ".b()"); }
}

aspect A {
    pointcut testing() :  
        cflow(execution(static void Replace.main(..))) && !within(A);

    /** replace B with new Mock before every method-call to B as I */   
    Object around(I targ) : testing() &&
        target(targ) && target(B) && call(* I.*(..)) {
        return proceed(new Mock());
    }
}
-----------


Back to the top