Let's use the same code example as in my answer to the related question about AspectJ unit testing :
The Java class should be aimed at the aspect:
package de.scrum_master.app; public class Application { public void doSomething(int number) { System.out.println("Doing something with number " + number); } }
Aspect under the test:
package de.scrum_master.aspect; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; @Aspect public class SampleAspect { @Around("execution(* doSomething(int)) && args(number)") public Object intercept(final ProceedingJoinPoint thisJoinPoint, int number) throws Throwable { System.out.println(thisJoinPoint + " -> " + number); if (number < 0) return thisJoinPoint.proceed(new Object[] { -number }); if (number > 99) throw new RuntimeException("oops"); return thisJoinPoint.proceed(); } }
You have several options, depending on what exactly you want to check:
- You can run the AspectJ compiler and check its output to the console (with weaving information turned on) to make sure that the expected connection points are actually intertwined and the others are not. But this will likely be a test for your AspectJ configuration and the build process itself, rather than a real integration test.
- Similarly, you can create a new weaving class loader, load the aspect, and then several classes (load time in time, LTW) to dynamically check what is woven and what is not. In this case, you are more likely to check if your pointcuts are correct than an integrated application consisting of core code + aspect.
- Last, but not least, you can perform a normal integration test, assuming that the application should behave after the kernel code + code has been properly gossiped. How to do this depends on the specific situation, namely on what side effect your aspect adds to the main code.
Subsequently, I will describe option No. 3. Looking at the code example above, we see the following side effects:
- For small positive numbers, the aspect goes through the value of the original parameter for the interception method, the only side effect is an additional log output.
- For negative numbers, the aspect goes through the value of the negation parameter (for example, turning -22 to 22) into the interception method, which is well tested.
- For large positive numbers, the aspect throws an exception effectively stopping the original method from executing.
Integration Test for Aspect:
package de.scrum_master.aspect; import static org.junit.Assert.assertEquals; import static org.mockito.ArgumentMatchers.matches; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import java.io.PrintStream; import org.junit.*; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.mockito.Mock; import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoRule; import de.scrum_master.app.Application; public class SampleAspectIT { @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); private Application application = new Application(); private PrintStream originalSystemOut; @Mock private PrintStream fakeSystemOut; @Before public void setUp() throws Exception { originalSystemOut = System.out; System.setOut(fakeSystemOut); } @After public void tearDown() throws Exception { System.setOut(originalSystemOut); } @Test public void testPositiveSmallNumber() throws Throwable { application.doSomething(11); verify(System.out, times(1)).println(matches("execution.*doSomething.* 11")); verify(System.out, times(1)).println(matches("Doing something with number 11")); } @Test public void testNegativeNumber() throws Throwable { application.doSomething(-22); verify(System.out, times(1)).println(matches("execution.*doSomething.* -22")); verify(System.out, times(1)).println(matches("Doing something with number 22")); } @Test(expected = RuntimeException.class) public void testPositiveLargeNumber() throws Throwable { try { application.doSomething(333); } catch (Exception e) { verify(System.out, times(1)).println(matches("execution.*doSomething.* 333")); verify(System.out, times(0)).println(matches("Doing something with number")); assertEquals("oops", e.getMessage()); throw e; } } }
Et voilร , we test only three types of side effects that our example has, checking the output of the log on a mock instance of System.out
and making sure that the expected exception is thrown for large positive numbers.
source share