xuanzhui xuanzhui - 1 year ago 68
Java Question

How to unit test java multiple thread

The issue is that I have a method starting a new thread for a time-consuming work. I want to test the callback result, but the child thread may still running, so as a result, what I get is not the right stub.

I think the code may explain itself:

public class JustAClass {
//it is a callback for async
public interface JustACallBack {
void callFunc(JustAResult result);

//this is the result interface
public interface JustAResult {

//this is a real class for the interface
public class JustAResultReal implements JustAResult{
public JustAResultReal(String content) {this.content = content;}
public String content;

//here is the key function
public void threadFunc(final JustACallBack callBack) {
BCCache.executorService.execute(new Runnable() {
public void run() {
//just to simulate a time-consuming task
try {
} catch (InterruptedException e) {

//now we callback
callBack.callFunc(new JustAResultReal("can you reach me"));

and the test function could be(I am using

public void testThreadFunc() throws Exception {

JustAClass justAClass = new JustAClass();

JustAClass.JustACallBack callBack = Mockito.mock(JustAClass.JustACallBack.class);


//add this line, we can get the expected result



I know we can add a
to wait and expect that the child thread would exit within the period, but could there be a better way? Actually how could I know how long the child thread would take? Setting a very long time can be an approach but just seems not very nice.

Answer Source

I aggree with @Gimbys comment about this is no longer a unit-test when you start testing the the threading aspect.

Nevertheless it is interesting as a way to integration-test a asynchronous invokation.

To avvoid sleep i tend to use the class CountDownLatch to wait for invokations. In order to count down you need an actuall implementation of the callback interface - so in my example I have made a mock implementation of this.

Since there is no actual methods to fetch the data - i am just testing that it is in fact a instance of the JustAReal interface.

public void testInvoke() throws Exception {

    final CountDownLatch countDownLatch = new CountDownLatch(1); //1 is how many invokes we are waiting for

    JustAClass justAClass = new JustAClass();
    JustAClass.JustACallBack callBack = new JustAClass.JustACallBack() {
        public void callFunc(final JustAClass.JustAResult result) {
            assertNotNull("Result should not be null", result);
            assertTrue("Result should be instance of JustAResultReal", result instanceof JustAClass.JustAResultReal);

    if(!countDownLatch.await(1200, TimeUnit.MILLISECONDS)){
        fail("Timed out, see log for errors");