views:

264

answers:

2

When writing aspects, how can I test that they do match and that they are invoked when I want them to?

I'm using @Aspect declarations with Spring 2.5.6.


I don't care about the functionality, that's extracted and tested otherwise.

+2  A: 

There's three different things to test here:

  1. Are your pointcuts matching what you expect?
  2. Do your advice reference the right pointcut?
  3. Does the advice do as you expect?

To test the pointcuts, you can define some test types that have the same package/type/method signatures as the intended "real" targets, then define a test advice against the pointcuts to ensure they are matched (also define some types that shouldn't be matched to ensure the pointcuts aren't too liberal). I usually do this by defining the advice to do a callback to a method in the test target, setting a flag, then assert the flag was set.

To test the advice is trickier. I tend to delegate all the advice body to a normal method, then focus on testing the method rather than the advice.

If you've done that, the only missing part is that your advice is applied to the correct pointcuts and actually calls the methods. If you're concerned this might be a problem you can do this by creating another aspect that matches your advice execution and sets a flag to show the expected delegated method was invoked by the aspect, and override the method to do nothing.

Rich Seller
+1  A: 

I ended up creating something which is a bit of an integration test, in the following way:

Created a Spring-aware JUnit test

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "aspects-test.xml" })
public class SomeAspectTest {

}

Created a spring configuration for this test which:

  • enables @AspectJ usage;
  • configures my aspect with dummy dependencies
  • declares a bean which should be picked up by the aspect

    <aop:aspectj-autoproxy />
    <bean class="SomeAspect">
     <property name="userDetailsSource">
                <bean class="StubUserDetailsSource"/>
     </property>
    </bean>
    <bean class="DummyService"/>
    

In the unit test I retrieve the dummy service and invoke its methods

@Autowired
private DummyService _dummyService;

@Test(expected = ApplicationSecurityException.class)
public void adminOnlyFails() throws ApplicationSecurityException {

    _dummyService.adminOnly();
}
Robert Munteanu