Since it has been introduced in JDK 1.5, I have loved the Executor abstraction over multi threaded execution. Basically you define tasks, implementing Runnable or Callable interfaces, and you submit those tasks to an Executor implementation, knowing that before or later the task will be processed. It's the Executor who knows how the tasks must be processed: scheduled at a certain time, enqueued in a separate single thread or using a thread pool. Different instances of Executor can be obtained through the Executors class.
In this way, the logic of your program is not dependent on how the multi threading needs to be implemented: you can think of tasks and executors, and you can choose, at a later time, how those tasks need to be processed. It's also possible to know what's the status of a task: have a look at the Future.

Another advantage that I like is the fact that you can remove the issue of the multi threading during the tests. Testing multi threaded code is in fact quite hard, because at the time you want to verify your assertions, the parallel threads may not yet be ready, so you have to play with sleep(), join(), wait() and notify() methods, producing sometimes unreliable tests.

So, wouldn't it be wonderful if, just for testing, you could remove the complexity of the multi threaded execution? After all, we know that Executors work beautifully and we don't need actually to verify them.
In fact, as Javadocs says

However, the Executor interface does not strictly require that execution be asynchronous. In the simplest case, an executor can run the submitted task immediately in the caller's thread:

 class DirectExecutor implements Executor {
     public void execute(Runnable r) {
         r.run();
     }
 }

Following the DIP principle, you can pass the above DirectExecutor to the class you want to test - I usually do it in the constructor - and, during the tests you have worked around the fact that something, in the real world, would happen in background. You can, in other words, flatten the multiple threads in a single thread.

Example:

String message = "hello world!";
Executor executor = new DirectExecutor();
Chat chat = new Chat(executor);
// suppose that the sendMessage sends messages in background (async)
chat.sendMessage(message); 
assertEqual(message, chatServer.lastMessageReceived()); 

Once we've used a DirectExecutor, we know that when we call the sendMessage(), the execution of the logic behind it will now be synchronous. Then, the assertion at the next line can evaluate the result without waiting that the "background" process to complete. No sleeps and no thread coordination needed anymore.

The DirectExecutor as listed in the javadocs can be improved to be more effective for the testing purpose. For example, with Mockito you can implement a direct executor with a Mock Object that can also be queried to verify how the class under test interact with it.

// on the base test class (MockitoTestBase)
@Before
public void before() {
    MockitoAnnotations.initMocks(this); 
} 

protected void implementAsDirectExecutor(ExecutorService executor) {
    doAnswer(new Answer<Object>() {
        public Object answer(InvocationOnMock invocation) 
            throws Exception {
            Object[] args = invocation.getArguments();
            Runnable runnable = (Runnable)args[0];
            runnable.run();
            return null;
        }
    }).when(executor).submit(any(Runnable.class));
} 

// on the subclass

@Mock private ExecutorService executor;

@Before
public void setUp() {
    implementAsDirectExecutor(executor);
} 

public void testChat() {
    String message = "hello world!";
    Chat chat = new Chat(executor);
    // suppose that sendMessage sends messages in background  (async)
    chat.sendMessage(message);
    // verify that the submit method has been invoked
    Mockito.verify(executor, times(1)).sumit(...);
    assertEqual(message, chatServer.lastMessageReceived()); 
}

In the above example I used an ExecutorService, which is a sub-interface of Executor, and provides additional features (like shutting down the executor and being able to reject tasks). But substantially it's more or less the same.

Once we've tested that our class works fine with an instance of a DirectExecutor, we may assume that substituting that with a different one, our code will reasonably behave correctly. Of course, you still have to keep in mind that the task will be executed in background and understand if you really covered your use case fully.


3 Responses to “Workaround to multi threaded testing”  

  1. 1 Luigi

    Testing concurrency issues is like experimenting on quantum physics. :-)

  2. 2 Bruno Bossola

    Just run into a similar issue, but this time I wanted to check if the execution was asynchronous.

    I have a service (EmailService) that is supposed to send an email trough an Emailer.
    (real code is a bit different, but anyway, gives you the overall idea)

    public interface EmailService {
        public void post(Email email);
    }
    public interface Emailer {
        public void send(Email email);
    }
    

    I just used a trick like this:

        public void shouldSendBeAsynchronous() {
            
            // collect the thread used by the send() method of the emailer 
            final Thread[] sendThread = new Thread[1];
            doAnswer(new Answer() {
                public Object answer(InvocationOnMock invocation) {
                    sendThread[0] = Thread.currentThread();
                    return null;
                }}).when(emailer()).send(anyObject());
            
            service.post(mail);
    
            service.executor.shutdown();
            assertFalse(Thread.currentThread().equals(sendThread[0]));
        }
    
    

    Two awful tricks:
    – access to the executor, necessary to perform shutdown
    – the array of thread used to collect a parameter passed to an inner class

    Open to improvements :)

    (…and for the other tests I used your mocked direct executor, thx! )

  3. 3 Gavin

    You really shouldnt mock an interface you dont own.

    Or so they tell us.

Leave a Reply

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>



Calendar

September 2010
M T W T F S S
« Aug   Oct »
 12345
6789101112
13141516171819
20212223242526
27282930  

Follow me

twitter flickr LinkedIn feed

Subscribe by email

Enter your email address:

Archives


Categories

Tag Cloud


Listening