Asynchronous Service Testing

When testing asynchronous services it is generally necessary to block runtime shutdown until a message has been processed or a callback received. Since message reception may happen on a different thread than the forward call, a race condition may occur where runtime shutdown is initiated before processing has completed.

The Gradle and Maven plugins provide the ability to define a latch in an test composite that the runtime will wait on prior to initiating shutdown. The latch can be released from test code when necessary conditions are met.

The latch component can implement any interface with an await() method:

public interface LatchService {
    void countDown();

    void await() throws InterruptedException;
}

@Component(name="F3LatchService")
@Scope("COMPOSITE")
public class LatchServiceImpl implements LatchService {
    private CountDownLatch latch = new CountDownLatch(1);

    public void countDown() {
        latch.countDown();
    }

    public void await() throws InterruptedException {
        latch.await();
    }
}

The latch service must be configured with the name "F3LatchService". Note also it is important the latch service implementation be composite scope; otherwise different instances will be returned to the runtime and test code, resulting in the runtime latch never being released.

When integration tests are run, the runtime will block on the await() method after running JUnit test components. Test code is then responsible for invoking the countDown() method when asynchronous test processing has completed. To do this, simple inject the LatchService on JUnit components where the countDown method should be called.