The Best Restroom in the USA XML HTTP Request object (and named parameters)
Nov 08

aUnit: Unit Testing Aspects

Tech Add comments

Adrian Colyer got me excited when I saw a post to the AspectJ list with the subject Announcing aUnit, a new unit testing tool for aspects.

How do you unit test aspects in isolation, in the same way that we might unit test a class?

Current unit-testing approaches for aspects are lacking in the following
ways:

* you cannot easily unit test an individual aspect in isolation from the rest of the program
* you cannot easily test whether the pointcut expression associated with a piece of advice matches the join points you expect
* you cannot easily test whether the pointcut expression associated with a piece of advice matches unwanted join points
* you cannot easily test the body of advice in isolation from the rest of the program

For example, given the following simple aspect:

public aspect X {

pointcut anInterestingCall() : call(* Account+.do*(..)) && within(org.xzy..*);

before() : anInterestingCall() { … }

}

We would like to write unit tests that verify:
* the pointcut matches a call to Account.doFoo() from within org.xyz.abc
* the pointcut matches a call to SubAccount.doGoo(int x) from within org.xyz.abc.def
* the pointcut does not match a call to Account.doFoo() from within org.qpr
* after matching at a join point, the post-conditions of the advice body are established
* and so on…

and we want to write these tests without necessarily having to create a package “org.qpr” and without having to weave and run external classes (to the one under test) in order to run the test cases.

Enter aUnit, a seamless extension to JUnit that makes it easy to write unit tests for aspects. aUnit works by letting the test programmer specify a sequence of join points (either programmatically, or parsed from a string format) that are then “played back” to the aspect. It is then easy to test after each join point or set of join points whether the aspect has responded as desired. Contextual information at the join points required by any advice (such as the objects bound to this or target, or the values of arguments) can be supplied by the test case programmer – as either “real” objects or as mock objects, in accordance with normal unit testing conventions.

Here’s an example of a simple aUnit test case:

public void testCallMatching() {
String[] jps = new String[]({”call(void Account.doFoo()) within(org.xyz.abc)”});
X x = X.aspectOf();
playBack(jps,x);
assertInvoked(x,”before”,”1″);
// …
}

The exact style of the test cases has yet to be finalized, but this should give you the idea.

But then the kicker came in:

Where can I download a copy of aUnit?

Sadly, you can’t. It doesn’t exist yet. The idea came to me whilst I was out running in the woods this lunchtime.

BUT, aUnit would make a great project for an MSc and/or for open-source development.

<jon stewart mock voice>
damn you adrian! :)
</jon stewart mock voice>

Ron Bodkin stepped up with good ideas (as always). He has done good work on Virtual Mocks with AOP:

I also think the design for a tool like this should be integrated with a similar API style as virtual mocks for objects (e.g., VirtualMock.org and the virtual mock framework in aTrack’s library). Virtual Mock frameworks typically provide means to specify simulated behavior, including simulated return results (which would be important for testing advice too), and allow instrumenting objects under test to determine what methods and arguments were called or executed (just as this code snippet suggests is needed in assertInvoked).

There’s another little fly in the ointment here: because advice is not named, it’s hard to test for a specific piece of advice being invoked. There is a trick available for naming advice: you can use an inner aspect with just one piece of advice to name the advice. When AspectJ supports Java 5.0, hopefully we will be able to annotate advice to give it a name. By the way, are you planning to allow annotations on advice and aspects in the first version of AspectJ with Java 5.0 support?

As we can see, there are definitely areas to explore with unit testing our aspects, and it will be great to have something like aUnit in the future.

Leave a Reply

Spam is a pain, I am sorry to have to do this to you, but can you answer the question below?

Q: Type in the word 'ajax'