About Me

My photo
I'm project manager of a software development team at www.researchspace.com. I've been developing bioinformatics software for the last 9 years or so, and I'm hoping to share some of the experience and knowledge I've gained with Eclipse RCP, Java web app development and software development in general on these blogs.

Tuesday, 4 November 2014

Running multithreaded JUnit tests with Apache Shiro

In this post I'm  going to explain how to run JUnit tests that simulate multiple users logged in simultaneously in a Java web application, using the Apache Shiro security library. Although the motivation for this is based on a specific use case of a current project, the test framework should be useful for anyone wanting to perform multithreaded unit tests with users authenticated in concurrent sessions -  perhaps to test resource contention, permissions, or locking.


In a web project I'm working on just now, users can share and edit documents. Because of the potential for people overwriting other people's edits, or even deleting a document whilst someone else is working on it, we use a locking mechanism to ensure that only one person can edit the document at a time. The lock is acquired when someone starts editing, and is released when any of these conditions are true:
  • The user logs out.
  • The user session expires.
  • The user saves and closes the document.
This is a tricky scenario to develop automated tests for; the calculation on whether someone can edit or not depends on a whole range of factors, such as authorization permissions, the state of document itself (documents can be signed, for example, which prevents further edits), and whether someone else is editing it or not.

Our project uses the Apache Shiro  security library, a very versatile library that can be used in web and non-web projects, and has good support for testing. Up till now, though, all our tests ran in a single thread, with the result that only one user could be logged in at a time.
For our integration tests we needed to have:
  • Several users logged on simultaneously, simulating concurrent web sessions.
  • One user active at a time, whilst the other users wait.
  • Active session management, so that session expiration and  logout listeners would be triggered after session lifecycle events.


In this solution, we build on a mechanism discussed in a StackOverflow post about sequencing of threads. All the code discussed here is available on Github as a Maven project at https://github.com/otter606/shiro-multithread-junit. Just import into your IDE and run 

mvn test 

to run.

Setting up Shiro.

Shiro provides a TestUtils class in its documentation. Our unit test class can extend this, or include it as a helper class. In our example, for ease of explanation, we'll extend from it.
First of all, we'll just initialise a  regular SecurityManager, using a configuration file, shiro.ini at the root of the classpath - this is a standard approach to initialising Shiro.

 public static void readShiroConfiguration() {  
           Factory factory = new IniSecurityManagerFactory("classpath:shiro.ini");  
           SecurityManager securityManager = factory.getInstance();  

The shiro.ini file is very simple, it just defines three users and their passwords:
 user1 = password1  
 user2 = password2  
 user3 = password3  

The code to login a user, and bind to a particular thread is boiler-plate code that we can put in a utility method. 

 private Subject doLogin(User user) {  
      Subject subjectUnderTest = new Subject.Builder(SecurityUtils.getSecurityManager())  
      subjectUnderTest.login(new UsernamePasswordToken(user.getUsername(), user.getPassword()));  
      return subjectUnderTest;  

So, at the moment we just have some code to login a User - useful, but nothing new. Calling this method multiple times in the same thread is likely to lead to strange results, so now we need to set up a mechanism to run multiple threads in JUnit, where each thread performs actions for a particular user, in a sequenced manner, so that the other threads pause when one thread is active. In this manner, we can test a use case like:
  1. User1 logs in and accesses a resource R for editing.
  2. User2 logs in and and also requests to access R, but is rejected, as user 1 holds a lock,
  3. User1 closes resource R (but remains logged in).
  4. User2 now successfully accesses R.
  5. User1 logs out.
  6. User2 logs out.

 Invokables and CountDown latches.

To run the test, we'll use a simple interface, Invokable, in which to define callback functions that perform a single step in the use case.
 public interface Invokable {  
   void invoke() throws Exception;  

And let's define an array of these - 6 long - to hold each action:
 Invokable[] invokables = new Invokable[6];  
 invokables[0] = new Invokable() {  
             // annotate these inner class methods with @Test  
     public void invoke() throws Exception {  
         log.info("logging in user1");  
         log.info(" user1 doing some actions..");  
         log.info(" user1 pausing but still logged in.");  
 invokables[1] = new Invokable() {  
     public void invoke() throws Exception {  
         log.info("logging in user2");  
         log.info(" user2 doing some actions..");  
         // some action  
         log.info(" user2 pausing but still logged in.");  
 //.. + 4 more Invokables defined for subsequent steps.

Now, we'll set up a mechanism to sequence the execution of these Invokables in different threads using a CountDown Latch mechanism. Here's how we'll call it:
 Map config = new TreeMap<>();  
 // these are the array indices of the Invokable [].  
 config.put("t1", new Integer[] { 0, 3 });  
 config.put("t2", new Integer[] { 1, 5, });  
 config.put("t3", new Integer[] { 2, 4 });  
 SequencedRunnableRunner runner = new SequencedRunnableRunner(config, invokables);  

In the code above, we define that  we want to run 3 threads, and specify the indices of the Invokable [] that will run in each thread. I.e., we want Invokable[0] to run in thread t1, then invokable 1 to run in thread t2, etc.,

What happens under the hood in runSequence is as follows. We define an array of CountDownLatch objects. Each Invokable will wait on a CountDownLatch, and each latch will be counted down by the completion of its predecessor:

 public void runSequence() throws InterruptedException {  
 // Lock l = new ReentrantLock(true);  
 CountDownLatch[] conditions = new CountDownLatch[actions.length];  
 for (int i = 0; i < actions.length; i++) {  
 // each latch will be counted down by the action of its predecessor  
 conditions[i] = new CountDownLatch(1);  
 Thread[] threads = new Thread[nameToSequence.size()];  
 int i = 0;  
 for (String name : nameToSequence.keySet()) {  
    threads[i] = new Thread(new SequencedRunnable(name, conditions, actions,  
 for (Thread t : threads) {  
 try {  
 // tell the thread waiting for the first latch to wake up.  
 } finally {  
   // l.unlock();  
 // wait for all threads to finish before leaving the test  
 for (Thread t : threads) {  

In SequenceRunnable, we run an Invokable, and count down the next latch in the sequence:
 public void run() {  
   try {  
     for (int i = 0; i < sequence.length; i++) {  
       int toWaitForIndx = sequence[i];  
       try {  
         log.debug(name + ": waiting for event " + toWaitForIndx);  
       } catch (InterruptedException e) {  
     log.debug(name + ": invoking action " + toWaitForIndx);  
     if (toWaitForIndx < toWaitFor.length - 1) {  
       log.debug(name + "counting down for next latch " + (toWaitForIndx + 1));  
     } else  
       log.debug(name + " executed last invokable!");  
   } catch (Exception e) {  

That's it! Using this setup, we can login multiple users simultaneously in concurrent sessions, and perform actions for any user  in a guaranteed order, thus being able to test thoroughly functionality that is affected by resource contention or locking.


In this blog, I've described how you can combine Shiro and JUnit to develop realistic integration tests for functionality that is  affected by concurrency. Thanks for reading!