How to run jetty server for java junit testing

LifeStartsAtHelloWorld picture LifeStartsAtHelloWorld · Apr 20, 2015 · Viewed 19k times · Source

I am trying to write an integration test to spin up jetty server locally and then use client to communicate with the rest URI and call the business logic downstream. However, when I start my jetty server it does not relinquish the control, so my client is not executed. So I used threading to start my jetty in a different thread, however, the thread finishes before my client call, it says connection refused. Any approach I can take?

@Test
public void testPerform() {

    final JettyServer jettyServer = JettyServer.create();
    jettyServer.buildJettyServer(ServletContextHandler.SESSIONS, "/", 8080, TestResource.class);

    Runnable runnable = new Runnable()
    {
        @Override
        public void run()
        {
            jettyServer.start();
        }
    };

    new Thread(runnable).start();

    final javax.ws.rs.client.Client client = ClientBuilder.newClient();

    final Response response = client.target("http://localhost:8080/test").request().post(Entity.text(""));

    jettyServer.stop();
}

Answer

Joakim Erdfelt picture Joakim Erdfelt · Apr 21, 2015

Skip the Runnable, skip the new Thread(runnable).start()

The call jettyServer.start() starts the server on its own thread (along with all of the other threads that the server needs.

For a basic example of junit and jetty ...

@Test
public void testGet() throws Exception
{
    // Create Server
    Server server = new Server(8080);
    ServletContextHandler context = new ServletContextHandler();
    ServletHolder defaultServ = new ServletHolder("default", DefaultServlet.class);
    defaultServ.setInitParameter("resourceBase",System.getProperty("user.dir"));
    defaultServ.setInitParameter("dirAllowed","true");
    context.addServlet(defaultServ,"/");
    server.setHandler(context);

    // Start Server
    server.start();

    // Test GET
    HttpURLConnection http = (HttpURLConnection)new URL("http://localhost:8080/").openConnection();
    http.connect();
    assertThat("Response Code", http.getResponseCode(), is(HttpStatus.OK_200));

    // Stop Server
    server.stop();
}

The @Before and @After junit annotations can also be used. This will start the server before each @Test and stop the server after.

package jetty;

import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;

import java.net.HttpURLConnection;
import java.net.URL;

import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.DefaultServlet;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

public class JUnitBeforeAfterJettyTest
{
    private Server server;

    @Before
    public void startJetty() throws Exception
    {
        // Create Server
        server = new Server(8080);
        ServletContextHandler context = new ServletContextHandler();
        ServletHolder defaultServ = new ServletHolder("default", DefaultServlet.class);
        defaultServ.setInitParameter("resourceBase",System.getProperty("user.dir"));
        defaultServ.setInitParameter("dirAllowed","true");
        context.addServlet(defaultServ,"/");
        server.setHandler(context);

        // Start Server
        server.start();
    }

    @After
    public void stopJetty()
    {
        try
        {
            server.stop();
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }

    @Test
    public void testGet() throws Exception
    {
        // Test GET
        HttpURLConnection http = (HttpURLConnection)new URL("http://localhost:8080/").openConnection();
        http.connect();
        assertThat("Response Code", http.getResponseCode(), is(HttpStatus.OK_200));
    }
}

For the best approach, you can also use the @BeforeClass and @AfterClass techniques, along with auto-binding to an open port. This will only start the server once, per Test Class, run all of the @Test methods, then stop the server once at the end.

package jetty;

import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;

import java.net.HttpURLConnection;
import java.net.URI;
import java.net.URL;

import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.servlet.DefaultServlet;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;

public class JUnitBeforeAfterClassJettyTest
{
    private static Server server;
    private static URI serverUri;

    @BeforeClass
    public static void startJetty() throws Exception
    {
        // Create Server
        server = new Server();
        ServerConnector connector = new ServerConnector(server);
        connector.setPort(0); // auto-bind to available port
        server.addConnector(connector);

        ServletContextHandler context = new ServletContextHandler();
        ServletHolder defaultServ = new ServletHolder("default", DefaultServlet.class);
        defaultServ.setInitParameter("resourceBase",System.getProperty("user.dir"));
        defaultServ.setInitParameter("dirAllowed","true");
        context.addServlet(defaultServ,"/");
        server.setHandler(context);

        // Start Server
        server.start();

        // Determine Base URI for Server
        String host = connector.getHost();
        if (host == null)
        {
            host = "localhost";
        }
        int port = connector.getLocalPort();
        serverUri = new URI(String.format("http://%s:%d/",host,port));
    }

    @AfterClass
    public static void stopJetty()
    {
        try
        {
            server.stop();
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }

    @Test
    public void testGet() throws Exception
    {
        // Test GET
        HttpURLConnection http = (HttpURLConnection) serverUri.resolve("/").toURL().openConnection();
        http.connect();
        assertThat("Response Code", http.getResponseCode(), is(HttpStatus.OK_200));
    }
}