Announcement Announcement Module
Collapse
No announcement yet.
Acegi and JUnit Page Title Module
Move Remove Collapse
This topic is closed
X
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Acegi and JUnit

    I searched through the source tree but couldn't find anything more specific...

    Is there a class or an example that shows how you can use JUnit to test Acegi-protected business services?

    Here's what I came up with so far, based on another post I saw last month, but I get an exception about not having an authorizer for the TestingAuthenticationToken.

    Code:
    public abstract class SpringEnabledTestCase extends TestCase {
    
        /**
         * Our logging object.
         */
        protected transient final Log log = LogFactory.getLog(getClass());
    
        /**
         * The factory used to create DB Sessions.
         */
        protected SessionFactory sessionFactory = null;
    
        /**
         * Our session's default mode is AUTO, but you can set it to COMMIT and NEVER
         */
        protected FlushMode flushMode = FlushMode.AUTO;
    
        /**
         * All Hibernate DAO tests will use the same Spring BeanFactory.
         */
        private static ApplicationContext ctx = null;
    
        // This static block ensures that Spring's BeanFactory is only loaded once for all tests
        static {
            ctx = new ClassPathXmlApplicationContext(Constants.SPRING_APPLICATION_CONTEXT_CONFIG_FILE);
        }
    
        /**
         * Basic constructor.
         */
        public SpringEnabledTestCase() {
            super();
        }
    
        /**
         * Before each Test Case method is triggered, make the DB session available to Spring's transaction support.
         */
        protected void setUp() throws Exception {
    
            super.setUp();
            sessionFactory = (SessionFactory) getApplicationContext().getBean(Constants.SESSION_FACTORY_CONTEXT_NAME);
            Session dbSession = SessionFactoryUtils.getSession(sessionFactory, true);
            dbSession.setFlushMode(flushMode);
            if (TransactionSynchronizationManager.hasResource(sessionFactory)) {
                log
                        .warn("TransactionSynchronizationManager already has a session factory!  Look at the preceeding code for missing super() calls, etc.");
            }
    
            TransactionSynchronizationManager.bindResource(sessionFactory, new SessionHolder(dbSession));
            
            // Create and store the Acegi SecureContext into the ContextHolder
            createSecureContext();
    
        }
    
        /**
         * After each Test Case method is done, flush and close the DB session.
         */
        protected void tearDown() throws Exception {
            
            // Remove the Acegi SecureContext from the ContextHolder
            destroySecureContext();
    
            SessionHolder holder = (SessionHolder) TransactionSynchronizationManager.unbindResource(sessionFactory);
            Session dbSession = holder.getSession();
    
            if (dbSession.getFlushMode() != FlushMode.NEVER) {
                dbSession.flush();
            }
    
            SessionFactoryUtils.closeSessionIfNecessary(holder.getSession(), sessionFactory);
            super.tearDown();
    
        }
    
        /**
         * Returns the initialized ApplicationContext.
         * 
         * @return The initialized ApplicationContext
         */
        protected ApplicationContext getApplicationContext() {
            return ctx;
        }
    
        /**
         * Creates an Acegi SecureContext and stores it on the ContextHolder
         */
        private static void createSecureContext() {
            
            TestingAuthenticationToken auth = new TestingAuthenticationToken("test", "test", new GrantedAuthority[] {
                    new GrantedAuthorityImpl("ROLE_TELLER"), new GrantedAuthorityImpl("ROLE_PERMISSION_LIST") });
    
            SecureContextImpl secureContext = new SecureContextImpl();
            secureContext.setAuthentication(auth);
            ContextHolder.setContext(secureContext);
            
        }
    
        /**
         * Removed the Acegi SecureContext from the ContextHolder
         */
        private static void destroySecureContext() {
            ContextHolder.setContext(null);
        }
    
    }
    Now here's the JUnit trace from a service unit test that extends SpringEnabledTestCase.

    Code:
    net.sf.acegisecurity.providers.ProviderNotFoundException: No authentication provider for net.sf.acegisecurity.providers.TestingAuthenticationToken
    	at net.sf.acegisecurity.providers.ProviderManager.doAuthentication(ProviderManager.java:136)
    	at net.sf.acegisecurity.AbstractAuthenticationManager.authenticate(AbstractAuthenticationManager.java:49)
    	at net.sf.acegisecurity.intercept.AbstractSecurityInterceptor.interceptor(AbstractSecurityInterceptor.java:294)
    	at net.sf.acegisecurity.intercept.method.MethodSecurityInterceptor.invoke(MethodSecurityInterceptor.java:82)
    	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:138)
    	at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:152)
    	at $Proxy6.get(Unknown Source)
    	at com.a4technologies.auditpoint.service.test.ReportServiceTest.testGet(ReportServiceTest.java:79)
    	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    	at java.lang.reflect.Method.invoke(Method.java:324)
    	at junit.framework.TestCase.runTest(TestCase.java:154)
    	at junit.framework.TestCase.runBare(TestCase.java:127)
    	at junit.framework.TestResult$1.protect(TestResult.java:106)
    	at junit.framework.TestResult.runProtected(TestResult.java:124)
    	at junit.framework.TestResult.run(TestResult.java:109)
    	at junit.framework.TestCase.run(TestCase.java:118)
    	at junit.framework.TestSuite.runTest(TestSuite.java:208)
    	at junit.framework.TestSuite.run(TestSuite.java:203)
    	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:421)
    	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:305)
    	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:186)
    Thanks in advance, Scott

  • #2
    Add a net.sf.acegisecurity.providers.TestingAuthenticati onProvider bean to your net.sf.acegisecurity.providers.ProviderManager bean in the application context. Note you shouldn't do this in a production application context (just your test case application context).

    The other issue is whether it makes sense to test your business methods when security is enabled. We provide the classes, but unless the business methods actually interact with the ContextHolder or say the access control list package, it is probably adding complexity to your test case without adding corresponding value.

    Comment


    • #3
      Originally posted by Ben Alex
      The other issue is whether it makes sense to test your business methods when security is enabled. We provide the classes, but unless the business methods actually interact with the ContextHolder or say the access control list package, it is probably adding complexity to your test case without adding corresponding value.
      Good point - I'll just test using my TransactionProxyFactoryBeans instead of using their security wrappers. Thanks!
      Scott

      Comment

      Working...
      X