Results 1 to 10 of 10

Thread: adding aspects on Junit methods

  1. #1
    Join Date
    Apr 2011
    Posts
    13

    Default adding aspects on Junit methods

    Hello,

    I'm new to Spring and I would like to use this framework to add aspects to my Junits test methods.

    For exemple, add logging before and after each test method ( this is just an exemple, the point is that i want to apply pointcuts on Junit test methods).

    I defined my pointcut :

    @Pointcut("execution(public * *.test*(..))")
    public void printaspect() {
    }


    And my advice :

    @Around("printaspect()")
    public Object log(ProceedingJoinPoint pjp) throws Throwable {
    System.out.println("aspect for method :" + pjp.getSignature().getName());
    Object o = pjp.proceed();
    return o;
    }


    The problem is that if I run Junit testcases, my pointcut is never reached...

    Can anyone help me please?

    thanks.

    Stéphane

  2. #2
    Join Date
    Jul 2010
    Location
    Venice, Italy
    Posts
    709

    Default

    Do you correctly use Spring JUnit support to load your application context and make it available in your test case for dependency injection? Post your configuration and a test class you're using...

  3. #3
    Join Date
    Apr 2011
    Posts
    13

    Default

    Hello,

    thanks for helping me !

    Here is my testApplicationContext.xml

    Code:
    <?xml version="1.0" encoding="UTF-8"?>
    <p:beans xmlns:p="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
      xsi:schemaLocation="http://www.springframework.org/schema/beans 
      http://www.springframework.org/schema/beans/spring-beans-2.0.xsd 
      http://www.springframework.org/schema/aop 
      http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">
    
      <aop:aspectj-autoproxy />
    
      <p:bean id="aspectClass" class="xx.yyy.zzz.AspectClass" />
    
      <p:bean name="/DeclarationSearchAction" class="xx.yyy.zzz.DeclarationSearchAction" />
    
      <p:bean id="DeclarationSearchActionTest" class="xx.yyy.zzz.DeclarationSearchActionTest" />
    
    </p:beans>

    My AspectClass :

    Code:
    @Aspect
    public class DimonaStrutsActionPreExecuteNotifier {
    
        @Pointcut("execution(public * *.test*(..))")
        public void printaspect() {
        }
    
        @Around("printaspect()")
        public Object log(ProceedingJoinPoint pjp) throws Throwable {
            System.out.println("aspect for method :" + pjp.getSignature().getName());
            Object o = pjp.proceed();
            return o;
        }
    }

    And My Junit ( which in fact will be a MockStrutsTestCase test )

    Code:
    @ContextConfiguration(locations="/testApplicationContext.xml")
    public class DeclarationSearchActionTest extends MockStrutsTestCase{
    
        public DeclarationSearchActionTest(String testName) {
            super(testName);
        }
        
        public DeclarationSearchActionTest(){
            
        }
        
        @Override
        protected void setUp() throws Exception {
            super.setUp();
            setContextDirectory(new File("src/main/webapp/"));
            setConfigFile("/WEB-INF/test-struts-config.xml");
            // Choose which action we want to test
            setRequestPathInfo("/DeclarationSearchAction.do");
        }
        
        public void testMultipleresultListForward() {
            // FILL TESTDB WITH ONLY 2 OR MORE VALUES
            actionPerform();
            
            verifyForward("success");
        }
        
    }

    My execute method is well advised but not the testMethod.

  4. #4
    Join Date
    Jul 2010
    Location
    Venice, Italy
    Posts
    709

    Default

    I suggest you carefully read the Spring/JUnit integration chapter in the reference documentation. Your test class should extend AbstractJUnit4SpringContextTests (without that, the @ContextConfiguration annotation is pretty much useless: the application context will not be loaded!).

    If you correctly studied Spring AOP, you should realize it's proxy-based and works only on Spring beans. If you don't use the Spring DI mechanism to load your classes, they are invisible to Spring so AOP is evidently impossible. Once you extend AbstractJUnit4SpringContextTests, you will have your loaded ApplicationContext as a class object to use to obtain your already dependency-injected beans (with the getBean() method) and use them. This way, your classes will have aop applied on also in your tests.

  5. #5
    Join Date
    Apr 2011
    Posts
    13

    Default

    The problem is that my testClass must Extends MockStrutsTestCase ==> I cannot extend it with AbstractJUnit4SpringContextTests

    If I understand well, I must do a

    Code:
    context.getBean("MyTestClass")
    to allow AOP on MyTestClass. Is it right?


    Does it mean that I have to create a "TestRunnerClass" which load all Spring "TestClassBean" ( in order add those class in the context ) and than run the test execution from this "master class"?

    It would be something like this

    Code:
    @ContextConfiguration(locations="/testApplicationContext.xml")
    public class TestRunner extends AbstractJUnit38SpringContextTests{
        
        public static void main(String[] args) {
            ApplicationContext context = new ClassPathXmlApplicationContext("/testApplicationContext.xml");
            DeclarationSearchActionTest t= (DeclarationSearchActionTest) context.getBean("DeclarationSearchActionTest");
            
            t.run();
        } 
    }
    Thanks for help !!

  6. #6
    Join Date
    Jul 2010
    Location
    Venice, Italy
    Posts
    709

    Default

    No it's not like that...if you extend AbstractJUnit4SpringContextTests and mark your class with @ContextConfiguration, your application context is automatically loaded! So you can use it like that:

    Code:
    @ContextConfiguration(locations="/testApplicationContext.xml")
    public class MyTestForClassX extends AbstractJUnit4SpringContextTests{
    
        private ClassX classUnderTest;
    
        @Before
        public void setUp() throws Exception {
            classUnderTest = (ClassX) applicationContext.getBean("idOfBeanX");
        }
        
        @Test
        public void testMyMethodOfClassXNumber1() 
        {
            classUnderTest.methodNumber1();
            //asserts
        } 
    
        @Test
        public void testMyMethodOfClassXNumber2() 
        {
            classUnderTest.methodNumber2();
            //asserts
        }
    
        //...and so on
    }

  7. #7
    Join Date
    Apr 2011
    Posts
    13

    Default

    I think there is a misunderstanding.

    What I want is not to advise "classUnderTest " ( that did I already ).

    I want to advise the testClass. To do some action before the execution of all test* methods.

    In your example, the classUnderTest is loaded in the context so the AOP can be applied. But the MyTestForClassX is not in the context .

    Am I right?

  8. #8
    Join Date
    Jul 2010
    Location
    Venice, Italy
    Posts
    709

    Default

    Ok now I understand...but isn't the @Before annotation there just to do the stuff you need to do before starting the tests?

    If you need to do the same stuff in all your tests, then put this stuff in a static method inside an utility class, and call this method in the @Before marked method for every test case...this is not something in which it is useful to use AOP, there is really no need to complicate something very simple...

  9. #9
    Join Date
    Apr 2011
    Posts
    13

    Post

    In fact, wat I'm try to do is to inject a mock object inside my StrutsActionClass.

    I found this article :

    http://www.javaworld.com/javaworld/j...st.html?page=1

    and tried to implement this solution qui spring AOP.

    => I need a pointcut which advise all test* method....

    the @Before doesn't match my needs ( even if I would prefer )

  10. #10
    Join Date
    Apr 2011
    Posts
    13

    Default

    In found a (not perfect) solution :

    I create a third-part class to launch my tests :

    Code:
        public void testRunAllTestCases() throws Exception {
            ApplicationContext context = new ClassPathXmlApplicationContext("/testApplicationContext.xml");
            DeclarationSearchActionTest t = (DeclarationSearchActionTest) context.getBean("DeclarationSearchActionTest");
           
            t.testMethod1();
            t.testMethod2();
        }
    }
    in this way, the testClass is in the context and can be advised with aop.

    This is not a perfect solution but for now, i will do with it ;-)

    Thanks for help.

    Stéphane

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •