A New Way to Test Your Multithreaded Code With JUnit

DZone 's Guide to

A New Way to Test Your Multithreaded Code With JUnit

In the following you see a simple example on how to test multithreaded Java code with JUnit.

· Java Zone ·
Free Resource

In the following you see a simple example on how to test multithreaded Java code with JUnit. Suppose we want to create a counter which can be used concurrently. So we start with the class Counter and the JUnit test TestCounter:

public class Counter {

    private int count=0;

    public void addOne()

    public int getCount()
        return count;
import static org.junit.Assert.assertEquals;
import org.junit.After;
import org.junit.Test;
import org.junit.runner.RunWith;
import com.anarsoft.vmlens.concurrent.junit.ConcurrentTestRunner;

public class TestCounter {

    private Counter counter = new Counter();

    public void addOne()

    public void testCount()
        assertEquals("4 Threads running addOne in parallel should lead to 4" , 4 , counter);


By using the RunWith annotation the JUnit test is run by a special ConcurrentTestRunner. This test runner runs the method annotated with “Test” parallel in 4 threads. After that it executes the methods marked with the annotation After” in the main thread.
If we run the test case with a race condition catcher like vmlens we see the following:
We have a race condition accessing the field count. To solve this we declare count as volatile and run the test again.

private volatile int count=0;

Now the test case succeeds. At least almost all the time. If you run the test case very often, you will sometimes see an assertion failed exception. To see what is going on, we run it with “Delay synchronization for unit tests” in vmlens enabled.

Now you will always see the following exception:

java.lang.AssertionError: 4 Threads running addOne in parallel should lead to 4 expected:<4> but was:<3>
    at org.junit.Assert.fail(Assert.java:88)
    at org.junit.Assert.failNotEquals(Assert.java:834)
    at org.junit.Assert.assertEquals(Assert.java:645)
    at TestCounter.testCount(TestCounter.java:21)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
    at com.anarsoft.vmlens.concurrent.junit.internal.InvokeListOfMethods.evaluate(InvokeListOfMethods.java:23)
    at com.anarsoft.vmlens.concurrent.junit.internal.ConcurrentStatement.evaluateStatement(ConcurrentStatement.java:12)
    at com.anarsoft.vmlens.concurrent.junit.ConcurrentTestRunner.evaluateStatement(ConcurrentTestRunner.java:212)
    at com.anarsoft.vmlens.concurrent.junit.ConcurrentTestRunner.runChildrenConcurrently(ConcurrentTestRunner.java:172)
    at com.anarsoft.vmlens.concurrent.junit.ConcurrentTestRunner.access$0(ConcurrentTestRunner.java:78)
    at com.anarsoft.vmlens.concurrent.junit.ConcurrentTestRunner$1.evaluate(ConcurrentTestRunner.java:72)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)

Actually count++ is not one operation but 6 byte code operations, containing one read and one write to the field count:

ALOAD 0: this
GETFIELD Counter.count : int
PUTFIELD Counter.count : int

By introducing a delay between those three operations, we make sure that two threads execute those operations in parallel. When executed in parallel the count will always be less then 4, sometimes 3 sometimes only 2.

To solve this we need to make those methods atomic. This can be done by using java.util.concurrent.atomic.AtomicInteger:

import java.util.concurrent.atomic.AtomicInteger;

public class Counter {

    private final AtomicInteger  count= new AtomicInteger();

    public void addOne()

    public int getCount()
        return count.get();

Now the test case always succeed. As test runner I used concurrent-junit, as race condition catcher I used vmlens

And although it is a fairly simple method, I realize that there are some tricky parts. Especially when you have to test more complicated classes. So, if you have any questions, just ask them in a comment below.

concurency, java, junit, testing

Published at DZone with permission of Thomas Krieger , DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}