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.
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. Some of the implementation of aUnit would need to be tied
to
AspectJ implementation details, and we would work with the
implementors to
make sure that the necessary interfaces are in place and assistance is
given. When finished, we would like aUnit to be contributed to the
AspectJ
tree under the CPL, to be included as part of the AspectJ distribution.
The project contains some non-trivial challenges (like how to
effectively
test around advice containing calls to proceed) that should make it
very
interesting to work on, and could form a core part of every AspectJ
developers toolkit.
It's something we'd love to work on but just don't have the time to
dedicate to it (hands full with Java 1.5 support).
So - do you want to build aUnit? I'd be very interested to hear from
developers or teams keen on taking on this challenge, or indeed from
anyone on the list who has ideas about what aUnit should be like.
-- Adrian
Adrian_Colyer@xxxxxxxxxx
_______________________________________________
aspectj-users mailing list
aspectj-users@xxxxxxxxxxx
http://dev.eclipse.org/mailman/listinfo/aspectj-users