2

I have a dummy project where I try figure out how to test pointcuts being triggered.

My project consists of 1 aspect bean which just prints after a foo method is called

@Component
@Aspect
public class SystemArchitecture {
    @After("execution(* foo(..))")
    public void after() {
        System.out.println("@After");
    }
}

And a FooServiceImpl with implemented foo method

@Service
public class FooServiceImpl implements FooService{
    @Override
    public FooDto foo(String msg) {
        return new FooDto(msg);
    }
}

The code works and and I can see "@After" being printed to console, but I can't check programatically if after pointcut was called using the test below.

@SpringBootTest
public class AspectTest {
    @Autowired
    private FooService fooService;

    @Test
    void shouldPass() {
        fooService.foo("hello");
    }
}

I've also tried using non-bean proxy as was adviced in https://stackoverflow.com/a/56312984/18224588, but this time I'm getting an obvious error cannot extend concrete aspect because my spy proxy is no longer viewed as an aspect:

public class AspectNoContextTest {
    @Test
    void shouldPass() {
        FooService fooService = Mockito.mock(FooService.class);
        SystemArchitecture systemArchitecture = Mockito.spy(new SystemArchitecture());
        
        AspectJProxyFactory aspectJProxyFactory = new AspectJProxyFactory(fooService);
        aspectJProxyFactory.addAspect(systemArchitecture);
        
        DefaultAopProxyFactory proxyFactory = new DefaultAopProxyFactory();
        AopProxy aopProxy = proxyFactory.createAopProxy(aspectJProxyFactory);

        FooService proxy = (FooService) aopProxy.getProxy();
        proxy.foo("foo");
        verify(systemArchitecture, times(1)).after();
    }
} 

1 Answers1

1

Ok, after some digging, I found that it's possible to accomplish this by making an aspect a @SpyBean. Also AopUtils can be used for performing additional checks

@SpringBootTest
public class AspectTest {
    @Autowired
    private FooService fooService;

    @SpyBean
    private SystemArchitecture systemArchitecture;

    @Test
    void shouldPass() {
        assertTrue(AopUtils.isAopProxy(fooService));
        assertTrue(AopUtils.isCglibProxy(fooService));


        fooService.foo("foo");

        verify(systemArchitecture, times(1)).after();
    }
}
  • 1
    You might also find my answers about [how to unit test aspects](https://stackoverflow.com/a/41407336/1082681) and [how to integration test aspects](https://stackoverflow.com/a/41453156/1082681) helpful. They apply to AspectJ without Spring, but can be used in Spring too (easpecially the unit-testing one), if you want to avoid using Spring test infrastructure. But if you are happy with you solution, it is fine too. I just want to add a bit of information for reference. – kriegaex Apr 19 '22 at 05:31