We're hiring!

We're actively seeking designers and developers for all three of our locations.

System Testing a Java Web Service in Jetty

Automated system tests are an invaluable part of ensuring your software product is functioning as intended. On many of our projects, we are lucky enough to work with languages and frameworks that have a number of testing tools built around them, making it relatively easy to create automated system tests.

However, there are times where the tools haven’t been made yet. Recently, we have been developing a large and complex Java web service for a client. We found that while we had access to a number of well-maintained testing libraries (JUnit, Mockito, Hamcrest), there weren’t any tools to create and run automated system tests against the web service.

So, we built a way to do it.

Our Java system tests had to be:

  • Automated
  • Configurable
  • Instrumented

Automated

In order to automate our system tests, we had to programmatically build and start the web service in Jetty. This was the most complex and difficult aspect of it. It required understanding how Jetty starts and bootstraps web applications. We also had to make sure Jetty could be properly shutdown after the tests ran.

public static void startJetty() throws Exception {
        configureServerProperties();
 
        configureServer();
 
        configureWebAppContext();
 
        configureWebAppDeployer();
 
        server.addLifeCycle(webAppDeployer);
        server.addHandler(context);
        server.start();
 
        while (server.isStarting()) {
            Thread.sleep(250);
        }
 
        findInjector();
    }

All the gritty details can be found here.

Configurable

Our web service had to connect to a number of external devices and services, which would have made it very difficult to system test certain aspects of it. Using the power of Guice, we were able to swap-in stubs that simulate the external devices and services.

In order to do this we had to:

  1. Ensure that external services were wrapped in Java interfaces.
  2. Ensure that the concrete implementations of those interfaces were swappable with different ones.
  3. Start and bootstrap our web service with a different module containing our stubs. (See here and here.)

Instrumented

Lastly, we wanted to be able to instrument various aspects of the application. For instance, we may want to create a number of entities in a database or alter the state of an object to trigger an event. We felt that the easiest way to do this would be to:

Finding a context listener was a bundle of fun:

private static void findInjector() {
        EventListener[] eventListeners = context.getServletContext().getContextHandler().getEventListeners();
        for (EventListener eventListener : eventListeners) {
            if (eventListener instanceof ApplicationServletContextListener) {
                injector = ((ApplicationServletContextListener) eventListener).backDoorToInjector();
                break;
            }
        }
    }

Again, all the details can be found here.

Example Java System Tests Project

We haven’t made this into a formal library (yet). However, an example project using all of the techniques described above has been put on GitHub and can be found here. The project was built using Maven and IntelliJ.
 

Justin DeWind (46 Posts)

This entry was posted in Web Apps and tagged , , . Bookmark the permalink. Both comments and trackbacks are currently closed.