PDA

View Full Version : Acegi and JUnit


smccrory
Sep 14th, 2004, 06:40 PM
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.


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_AP PLICATION_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(ses sionFactory)) {
log
.warn("TransactionSynchronizationManager already has a session factory! Look at the preceeding code for missing super() calls, etc.");
}

TransactionSynchronizationManager.bindResource(ses sionFactory, 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(s essionFactory);
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.


net.sf.acegisecurity.providers.ProviderNotFoundExc eption: No authentication provider for net.sf.acegisecurity.providers.TestingAuthenticati onToken
at net.sf.acegisecurity.providers.ProviderManager.doA uthentication(ProviderManager.java:136)
at net.sf.acegisecurity.AbstractAuthenticationManager .authenticate(AbstractAuthenticationManager.java:4 9)
at net.sf.acegisecurity.intercept.AbstractSecurityInt erceptor.interceptor(AbstractSecurityInterceptor.j ava:294)
at net.sf.acegisecurity.intercept.method.MethodSecuri tyInterceptor.invoke(MethodSecurityInterceptor.jav a:82)
at org.springframework.aop.framework.ReflectiveMethod Invocation.proceed(ReflectiveMethodInvocation.java :138)
at org.springframework.aop.framework.JdkDynamicAopPro xy.invoke(JdkDynamicAopProxy.java:152)
at $Proxy6.get(Unknown Source)
at com.a4technologies.auditpoint.service.test.ReportS erviceTest.testGet(ReportServiceTest.java:79)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Nativ e Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Native MethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(De legatingMethodAccessorImpl.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.ja va: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:2 08)
at junit.framework.TestSuite.run(TestSuite.java:203)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRu nner.runTests(RemoteTestRunner.java:421)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRu nner.run(RemoteTestRunner.java:305)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRu nner.main(RemoteTestRunner.java:186)



Thanks in advance, Scott

Ben Alex
Sep 14th, 2004, 07:55 PM
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.

smccrory
Sep 14th, 2004, 09:36 PM
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