49

I can unit test most of my Spring classes without needing to do Spring "stuff".

I can unit test @Before advice methods without using Spring too:

Example code:

@Before("execution(* run(..)) && " + "" +
          "target(target) && " +
        "args(name)")
public void logName(Object target, String name) {
    logger.info("{} - run: {}", target, name);
}

Example test:

@Test
public void testLogName() {
    aspect.setLogger(mockLogger);
    aspect.logName(this,"Barry");
    assertTrue(mockLogger.hasLogged("TestAspect - run: Barry"));
}

However @Around advice deals with a ProceedingJoinPoint object:

@Around("com.xyz.myapp.SystemArchitecture.businessService()")
public Object doBasicProfiling(ProceedingJoinPoint pjp) throws Throwable {
   // start stopwatch
   Object retVal = pjp.proceed();
   // stop stopwatch
   return retVal;
 }

I don't know how to instantiate a ProceedingJoinPoint object. How do I test this class without starting a whole Spring application context?

slim
  • 40,215
  • 13
  • 94
  • 127
  • Could you provide complete code, how you have implemented test case for @Before? I need help in implementing this. – kk. Dec 03 '17 at 19:05

1 Answers1

109

You can test a Spring Aspect by creating a proxy programatically:

MyInterface target = new MyClass();
AspectJProxyFactory factory = new AspectJProxyFactory(target);
MyAspect aspect = new MyAspect(arg);
factory.addAspect(aspect);
MyInterface proxy = factory.getProxy();

... then you can call methods on proxy, and make assertions about aspect, proxy and target.

slim
  • 40,215
  • 13
  • 94
  • 127
  • 1
    Great thx - finally I can properly test that stuff. Do you have any ideas why you have to do this programatically? I declared MyAspect as a bean and load this context in the unit test and so expected the aspect to be executed - but it only works the way you described her... – Alexander Hansen Oct 19 '12 at 07:54
  • Well *I* have to do it because by choice I don't use Spring in my unit tests. If you want to start a Spring context in your unit tests, then normal Spring considerations apply. – slim Oct 22 '12 at 11:01
  • What would the assertions look like? Do you have some examples? – mip Apr 14 '14 at 08:15
  • 1
    @mip just the same kind of assertions you'd make in normal jUnit testing; the details depend entirely on what your classes under test are supposed to do. For example if the Aspect is supposed to log something, assert that its OutputStream received the expected characters. – slim Apr 14 '14 at 09:18
  • My aspect inserts some date into a db table (for auditing purposes). It calls a method, say `auditPayment()`, is there a way I can verify that this has been called? – mip Apr 14 '14 at 10:50
  • 1
    @mip you need to learn about mocking. Mockito and JMock are two options. – slim Apr 14 '14 at 13:12
  • @slim got it sorted thanks. Confusion was around how the proxy worked. Cheers. – mip Apr 15 '14 at 10:25