Luigi is a passionate software developer working in Java since 2000. In 2001 he co-founded the Java User Group Torino, the first local JUG in Italy. Quickly after that, many other JUGs have born in Italy following JUG Torino's example. Since some years now, he is working as free lance software consultant between Italy, Germany, UK and Switzerland, on several industries. His personal interests include software, science fiction books and movies, traveling, photography and good food. Luigi is a DZone MVB and is not an employee of DZone and has posted 19 posts at DZone. You can read more from them at their website. View Full User Profile

Workaround to Multi Threaded Testing

09.08.2010
| 7627 views |
  • submit to reddit

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. 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 dependant 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 discover the status of a task: by taking 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 multithreaded code is 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 the 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 background execution? After all, we know that Executors work beautifully and we don't need actually to verify them.
In fact, as the Javadocs say

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 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 for 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 testing purposes. 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 subsantially 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 it 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 the background and understand if you really covered your use case fully.

From http://en.newinstance.it/2010/09/07/workaround-to-multi-threaded-testing/

Published at DZone with permission of Luigi Viggiano, author and DZone MVB.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Tags:

Comments

King Sam replied on Fri, 2012/02/24 - 9:39am

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.

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.