The author mentions that some mechanisms he discusses are AspectJ-specific, but that many should be portable to other aspect frameworks.
After showing patterns for testing aspects in four different categories:
- Testing integrated units: This section presents a pattern for testing a piece of an integrated system (in other words, testing both your aspects and non-aspect classes together). This technique is the only way to gain confidence in crosscutting behavior if you don't use aspects and remains a critical tool when you do use them.
- Using visual tools: The two patterns described here leverage
AspectJ's IDE support for Eclipse, also known as AJDT. Using visual tools to inspect your application's crosscutting structure is not a testing technique, strictly speaking. However, it will help you to understand and gain confidence in your application's crosscutting concerns. - Using delegation: This section demonstrates two patterns that help you tease apart the two failure types previously mentioned. By factoring some logic out of your advice and into a helper class (or method), you can write tests that check your application's crosscutting behavior independent of its crosscutting specification.
- Using mock targets: This final section includes three patterns introducing "mock targets," classes that mimic real advice targets and allow you to test the both join point matching and advice behavior without integrating your aspect it into a real target.
Testing aspects is a lot like testing objects. In both cases, you need to break the behavior into components that you can test independently. A key concept to grasp is that crosscutting concerns divide into two different areas. First, there is the crosscutting specification, where you should ask yourself what parts of the program the concern affects. Second, there is the functionality, where you should ask what happens at those points. If you are only using objects, these two areas intertwine as your concern tangles itself throughout your application. However, with aspects, you can target one or both of these areas in isolation.
Writing aspects to be testable yields design benefits parallel to those achieved by factoring object-oriented code for testability. For instance, if I move my advice body into an independently testable class, I can analyze the behavior without necessarily needing to understand the way it crosscuts the application. If I modify my pointcuts to make them more accessible to mock targets, I also make them more accessible to non-test parts of the system. In both cases, I increase the flexibility and pluggability of the system as a whole.