JUnit tests for AspectJ

后端 未结 1 619
渐次进展
渐次进展 2020-12-30 00:40

I am trying to write Junit tests for Custom Aspect. Here is the Aspect Class Snippet:

@Aspect
@Component
public class SampleAspect {

    private static Logg         


        
相关标签:
1条回答
  • 2020-12-30 01:08

    I think what you are trying to test is aspect weaving and pointcut matching. Please note that that would be an integration rather than a unit test. If you really want to unit test your aspect logic and because you have tagged the question by "mockito" anyway, I suggest you do just that: Write a unit test and mock the aspect's joinpoint and maybe its other parameters, if any. Here is a slightly more complex example with some intra-aspect logic:

    Java class to be targeted by aspect:

    package de.scrum_master.app;
    
    public class Application {
        public static void main(String[] args) {
            new Application().doSomething(11);
            new Application().doSomething(-22);
            new Application().doSomething(333);
        }
    
        public void doSomething(int number) {
            System.out.println("Doing something with number " + number);
        }
    }
    

    Aspect under 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();
        }
    }
    

    Console log when running Application.main(..):

    As you can see, the aspect passes on 11, negates -22 and throws an exception for 333:

    execution(void de.scrum_master.app.Application.doSomething(int)) -> 11
    Doing something with number 11
    execution(void de.scrum_master.app.Application.doSomething(int)) -> -22
    Doing something with number 22
    execution(void de.scrum_master.app.Application.doSomething(int)) -> 333
    Exception in thread "main" java.lang.RuntimeException: oops
        at de.scrum_master.aspect.SampleAspect.intercept(SampleAspect.aj:15)
        at de.scrum_master.app.Application.doSomething(Application.java:10)
        at de.scrum_master.app.Application.main(Application.java:7)
    

    Unit test for aspect:

    Now we really want to verify that the aspect does what it should and cover all execution paths:

    package de.scrum_master.aspect;
    
    import org.aspectj.lang.ProceedingJoinPoint;
    import org.junit.Rule;
    import org.junit.Test;
    import org.mockito.Mock;
    import org.mockito.junit.MockitoJUnit;
    import org.mockito.junit.MockitoRule;
    
    import static org.mockito.Mockito.*;
    
    public class SampleAspectTest {
        @Rule
        public MockitoRule mockitoRule = MockitoJUnit.rule();
    
        @Mock
        private ProceedingJoinPoint proceedingJoinPoint;
    
        private SampleAspect sampleAspect = new SampleAspect();
    
        @Test
        public void testPositiveSmallNumber() throws Throwable {
            sampleAspect.intercept(proceedingJoinPoint, 11);
            // 'proceed()' is called exactly once
            verify(proceedingJoinPoint, times(1)).proceed();
            // 'proceed(Object[])' is never called
            verify(proceedingJoinPoint, never()).proceed(null);
        }
    
        @Test
        public void testNegativeNumber() throws Throwable {
            sampleAspect.intercept(proceedingJoinPoint, -22);
            // 'proceed()' is never called
            verify(proceedingJoinPoint, never()).proceed();
            // 'proceed(Object[])' is called exactly once
            verify(proceedingJoinPoint, times(1)).proceed(new Object[] { 22 });
        }
    
        @Test(expected = RuntimeException.class)
        public void testPositiveLargeNumber() throws Throwable {
            sampleAspect.intercept(proceedingJoinPoint, 333);
        }
    }
    

    Now run this simple JUnit + Mockito test in order to test the aspect logic in isolation, not the wiring/weaving logic. For the latter you would need another type of test.

    P.S.: Only for you I used JUnit and Mockito. Usually I just use Spock and its built-in mocking capabilities. ;-)

    0 讨论(0)
提交回复
热议问题