سؤال

I am using the aspectj maven plugin to weave Aspects at compile time. When I run the application, the class with the @Advice annotation is being instantiated just before the first time the advice is called. For example:

@Aspect
public class MyAdviceClass {

    public MyAdviceClass() {
        System.out.println("creating MyAdviceClass");
    }

    @Around("execution(* *(..)) && @annotation(timed)")
    public Object doBasicProfiling(ProceedingJoinPoint pjp, Timed timed) throws Throwable {
        System.out.println("timed annotation called");
        return pjp.proceed();
    }
}

If I have a method using the @Timed annotation, the "creating MyAdviceClass" will be printed the first time that method is called and "timed annotation called" will be printed every time.

I would like to unit test the functionality of the advice by mocking some components in MyAdviceClass however can not do this because MyAdviceClass is instantiated by AspectJ just in time, not through Spring Beans.

What is the best practice method for unit testing something like this?

هل كانت مفيدة؟

المحلول

I have found the solution and would like to post it for anyone else that encounters this. The trick is using factory-method="aspectOf" in your spring bean definition. So using the example above, I would add this line to my applicationContext.xml

<bean class="com.my.package.MyAdviceClass" factory-method="aspectOf"/>

Any my unit test would look something like this:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:/META-INF/spring/applicationContext.xml")
public class MyAdviceClassTest {
    @Autowired private MyAdviceClass advice;
    @Mock private MyExternalResource resource;

    @Before
    public void setUp() throws Exception {
        initMocks(this);
        advice.setResource(resource);
    }

    @Test
    public void featureTest() {
        // Perform testing
    }
}

More details are available here.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top