Spring Security Authentication in Unit / Integration tests

The problem (briefly) : I have a set of domain applications. These applications are managed by authorized personnel. I have to implement a sandbox approach: users (persistence) actions are supposed to be isolated from each other. I have to support the notation of optimistic locking: if two sandbox users try to update the same item, each changes are maintained in isolation and a first commit wins policy must be enforced. Finders method return subset or superset of domain object collections and authorization policies should be enforced over business components and methods.


This article assumes basic knowledge of Spring Security concepts and API.


First I had to think of how would a sandbox identity can be maintained and carried throughout the application. This came up very easy: since I use Spring security for ... security, I just added a sandbox identifier to authenticated Principals, which can be propagated and used by the security Context.


public class SandBoxUser extends org.springframework.security.core.userdetails.User {

    private Integer sandBox;

    public SandBoxUser
            (String username, String password, boolean enabled, Integer sandBox,
             Collection<? extends org.springframework.security.core.GrantedAuthority> authorities)

        super(username, password, enabled, true, true, true, authorities);
        this.sandBox = sandBox;

    public Integer getSandBox() {
          return sandBox;



Fairly simple. A User class with an integer sandbox identity. I wouldn't get into details of how I've implemented the sandbox functionality in order to address the problems I've mentioned above, but briefly: I've used traditional mechanisms like AOP (which I'm controversial about), and Spring Security features like : @Secured, @PreAuthorize, and @PostFilter


For example:


public class SendBoxAssetDao {


Meaning that the DAO methods can only be accessed by users who are granted the ROLE_SB role.




@PreAuthorize("#sandBoxAsset.sandBox == principal.sandBox")
public void persist(SandBoxAsset sandBoxAsset) {


Meaning that this method can only accessed once the following permission evaluates to true : the method argument sandbox property equals the predefined evaluated expression principal sandbox property. The principal is of type SandBoxUser from above. How to wire all this, we'll see in a minute.


I've started the article by describing my problem. Well, I've a little bit cheated. The issues here, for those of you still following, is how to use all these authorization controls in conjunction with integration tests, where we don't have an authentication mechanism such as a login form. This is, as we shall soon see, is not complicated either.


The first step is to mock a security domain for users and roles. We'll start by showing the security context (securityContext.xml) config file:


<global-method-security pre-post-annotations="enabled" secured-annotations="enabled"/>

        <authentication-provider user-service-ref="userDetailsService"/>

<beans:bean id="userDetailsService" class="com.xxx.security.spring.AssetManagerUserDetailsService"/>


We enable Spring security pre-post annotaions (such as @PreAuthorize) and secured annotation. This one would fit our production system as well. Next we declare the authentication manager to have a mock user detail service. Let have a look at it:


public class AssetManagerUserDetailsService implements UserDetailsService {

    Map<String, Integer> users = new HashMap<String, Integer>(2);
        users.put("ori", 0);
        users.put("ofer", 1);
    HashSet<GrantedAuthority> roles = Sets.<GrantedAuthority>newHashSet(new GrantedAuthorityImpl("ROLE_SB"));

    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException {
        return new SandBoxUser(username, username, true, users.get(username), roles);


Indeed, not a very clever one, but serves out purpose: we create a sandbox user with the Sandbox identifier we retrieve from the map, using the username itself as a key.


So, now for the authentication itself. How is it done using (Spring test context) integration tests?

The answer, not suprisingly, is using Spring Security:


@ContextConfiguration(locations = {"/securityContext.xml"})
public abstract class MockSecurityIntegrationTests extends AbstractTestNGSpringContextTests {

    Map<Integer, String> users = new HashMap<Integer, String>(2);
        users.put(0, "ori");
        users.put(1, "ofer");
    HashSet<GrantedAuthority> roles = Sets.<GrantedAuthority>newHashSet(new GrantedAuthorityImpl("ROLE_SB"));

    public void authenticate() {
        int sb = new Random().nextBoolean() ? 1 : 0;
        String name = users.get(sb);
        SandBoxUser user = new SandBoxUser(name, name, true, sb, roles);
        UsernamePasswordAuthenticationToken token =  new UsernamePasswordAuthenticationToken(user, user.getPassword());


Again, we're using a map for mock values. Note however that the keys and values are flipped (compared to the authorization example). We create a sandbox user instance, pass it to a UsernamePasswordAuthenticationToken (which is basically a java.security.Principal) and authenticate it against security context. This is really how authentication is done. All the rest was just a sort of a preface.


As a quick test we'll define an authorization dependent Spring service:


public class MockRoleBaseSecurityService {
    public void allowedForSandBox() {

    public void disallowedForSandBox() {


We expect our sandbox user to pass through the first method invocation and be denied for the second one.

A simple test case can verify it:


public class RoleCheckIntegrationTests extends MockSecurityIntegrationTests {

    MockRoleBaseSecurityService service;

    public void allow() {

    @Test(expectedExceptions = {AccessDeniedException.class})
    public void deny() {
        fail("You're supposed to be unauthorized");   









Thank you for your interest!

We will contact you as soon as possible.

Send us a message

Oops, something went wrong
Please try again or contact us by email at info@tikalk.com