1. csolar
  2. jat

Overview

HTTPS SSH

Java Asynchronous Test (jat)

It's an extremely small (one class!) and easy to use framework to help with aynchronous code in your unit tests.

The use case

You are trying to junit test some kind of asynchronous process, say, client-server interaction where both client and server run on their own threads. The client uses callbacks to get notified about data from the server. To test server responses, you create a client, add your test code (assertions and all) within a callback and subscribe to server replies via this callback. There are two problems:

1 - The client and server are running on different threads than your junit test is. This means that the callback will not be invoked within the junit test thread therefore oops! the junit test will pass even if you have an assertion failure somewhere.

2 - This is an asynchronous process so the junit test does not know when/if the callback will finish. How long do we wait for the callback to finish? Otherwise, how do we synchronise the callback state with the junit test state?

What jat does

It help you with the following:

1 - It deals with synchronisation between the callback thread and the junit test thread so you don't have to.

2 - It passes assertion failures in the asynchronous code back to the main junit test thread so your junit test fails properly.

jat example

Suppose we had:

    import org.junit.After;
    import org.junit.Assert;
    import org.junit.Before;
    import org.junit.Test;

    public class ServerTest
    {
        private final FictionalServer server;
        private final FictionalClient client;

        @Before
        public void setUp()
        {
            server = new FictionalServer();
            Thread serverThread = new Thread(server);
            serverThread.start();
            client = new FictionalClient();
            Thread clientThread = new Thread(client);
            clientThread.start(); 
        }

        @After
        public void tearDown() throws IOException
        {
            server.close();
            server = null;
        }

        @Test(timeout = 10000)
        public void testServerIsAlive() throws Exception
        {
            FictionalCallback cb = new FictionalCallback()
            {
                @Override
                public void success(String message)
                {
                    Assert.assertNotNull(message);
                }
                @Override
                public void error(String message)
                {
                    Assert.fail();
                }
            };

            client.send(cb, "ping");
        }
    }

This is how it looks with jat:

    import org.junit.After;
    import org.junit.Assert;
    import org.junit.Before;
    import org.junit.Test;  
    import terseuniverse.net.jat.AsyncTest;

    public class ServerTest
    {
        private final FictionalServer server;
        private final FictionalClient client;

        @Before
        public void setUp()
        {
            server = new FictionalServer();
            Thread serverThread = new Thread(server);
            serverThread.start();
            client = new FictionalClient();
            Thread clientThread = new Thread(client);
            clientThread.start(); 
        }

        @After
        public void tearDown() throws IOException
        {
            server.close();
            server = null;
        }

        @Test(timeout = 10000)
        public void testServerIsAlive() throws Exception
        {
            final AsyncTest asyntest = new AsyncTest();

            FictionalCallback cb = new FictionalCallback()
            {
                @Override
                public void success(String message)
                {
                    AsyncTest.Test test = new AsyncTest.Test()
                    {
                        @Override
                        public void test()
                            throws AssertionError
                        {
                            Assert.assertNotNull(message);
                            // more assertions here...
                        }
                    };

                    asyntest.test(test);
                }
                @Override
                public void error(String message)
                {
                    asyntest.fail();
                }
            };

            client.send(cb, "ping");
            asyntest.await();
        }
    }