Monday, November 12, 2007

Mocking ACEGI security users

In one of my projects I had to test some features, using JUnit and JMock. The features that I had to test were based on roles assigned to an already logged user. I realized that I have to populate the SecurityContextHolder with some dummy user data to be able to test. Based on ACEGI Security source code of some tests I could find a solution for that (actually is the test case for BasicProcessingFilter class).

This is the code:

public class MyAcegiTest{

Mockery context = new Mockery();
private BasicProcessingFilter filter = new BasicProcessingFilter();

@Before
public void init() throws Exception{
// Cleaning any previous information on SecurityContextHolder
SecurityContextHolder.clearContext()

// Using in-memory DAO
InMemoryDaoImpl dao = new InMemoryDaoImpl();
UserMapEditor editor = new UserMapEditor();

// the user jsmith will have two roles, Manager and User, you can use whatever you need here.
editor.setAsText("jsmith=jsmith,ROLE_MANAGER,ROLE_USER,enabled\r\n");
dao.setUserMap((UserMap)editor.getValue());
DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
provider.setUserDetailsService(dao);

ProviderManager manager = new ProviderManager();
manager.setProviders(Arrays.asList(new Object[] {
provider
}));
// The mock for ApplicationEventPublisher is at the end of this class
manager.setApplicationEventPublisher(new MockApplicationEventPublisher());
manager.afterPropertiesSet();

// Setting up the filter
filter.setAuthenticationManager(manager);
filter.setAuthenticationEntryPoint(new BasicProcessingFilterEntryPoint());

}

@Test
public void mytest() throws Exception{
// The token represents as if the user has used a basic authentication form to log in.
String token = "jsmith:jsmith";

//Creating a mock request
MockHttpServletRequest request = new MockHttpServletRequest();

// Filling the request with the necesary headers and properties
request.addHeader("Authorization", "Basic " + new String(Base64.encodeBase64(token.getBytes())));
request.setServletPath("/test.do");
request.setMethod("POST");
request.setSession(new MockHttpSession());

//Here is where the magic is done. Checks the login information (on Authorization header)
//and populates the SecurityContextHolder with the user information creating the Authentication object
//, so you can use SecurityContextHolder.getContext().getAuthentication() after this line
filter.doFilter(request, response, new MockFilterChain());



}

private class MockApplicationEventPublisher implements ApplicationEventPublisher{

public MockApplicationEventPublisher(){}

public void publishEvent(ApplicationEvent event){}

}

}

0 comments: