Question

Jetty's ServletTester is pretty useful for testing Servlet apps. I have used Jetty 6's ServletTester before and it worked perfectly.

For example:

Jetty 6.x

pom.xml

<dependency>
  <groupId>org.mortbay.jetty</groupId>
  <artifactId>jetty-servlet-tester</artifactId>
  <version>6.1.26</version>
  <scope>test</scope>
</dependency>

SampleServletTest.java

package example;
import org.junit.Test;
import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*;
import org.mortbay.jetty.testing.HttpTester;
import org.mortbay.jetty.testing.ServletTester;

public class SampleServletTest {

    @Test
    public void testDoGet() throws Exception {
        ServletTester tester = new ServletTester();
        tester.addServlet(SampleServlet.class, "/index");
        tester.start();

        HttpTester request = new HttpTester();
        request.setMethod("GET");
        request.setHeader("Host", "tester"); // should be "tester"
        request.setURI("/index");
        request.setVersion("HTTP/1.1");
        request.setContent("");

        String responses = tester.getResponses(request.generate());
        HttpTester response = new HttpTester();
        response.parse(responses);

        assertThat(response.getStatus(), is(equalTo(200)));
    }
}

Jetty 9.x

ServletTester's APIs are much improved in Jetty 9.x.

pom.xml

<dependency>
    <groupId>org.eclipse.jetty</groupId>
    <artifactId>jetty-servlet</artifactId>
    <version>9.0.7.v20131107</version>
    <scope>test</scope>
</dependency>

SampleServletTest.java

package example;
import org.junit.Test;
import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*;
import org.eclipse.jetty.http.HttpTester;
import org.eclipse.jetty.servlet.ServletTester;

public class SampleServletTest {

    @Test
    public void testDoGet() throws Exception {
        ServletTester tester = new ServletTester();
        tester.addServlet(SampleServlet.class, "/index");
        tester.start();

        HttpTester.Request request = HttpTester.newRequest();
        request.setMethod("GET");
        request.setHeader("Host", "tester"); // should be "tester"
        request.setURI("/index");
        request.setVersion("HTTP/1.1");
        request.setContent("");

        HttpTester.Response response = HttpTester.parseResponse(tester.getResponses(request.generate()));

        assertThat(response.getStatus(), is(equalTo(200)));
    }
}

New API looks very cool but unfortunately above code runs much slowly... This code takes 10 seconds to run every time. Can you believe it?

Is there anyone who has knowledge of this issue? If this is just my mistake, it's very good news.

Was it helpful?

Solution

This is normal behavior for the request configuration you have.

It has to do with HTTP persistent connections.

Jetty 6's servlet tester defaulted to HTTP/1.0 behavior.

HTTP/1.0 has no official specification for persistent connections, but clients have evolved over the years to adopt a non-persistent behavior, which can be overridden with a negotiated Connection header.

With HTTP/1.0, its 1 request, then 1 response, then connection is closed. Unless the client sends a Connection: Keep-Alive header (and the server responds with the same header)

Jetty 9's HttpTester also defaults to HTTP/1.0.

You specified request.setVersion("HTTP/1.1"); in your example, where all connections are considered persistent unless declared otherwise. So adding Connection: close will force the server to close the connection after the response has been sent, not waiting for another request.

So you have 2 options here:

  1. Stick with HTTP/1.1 and also add request.setHeader("Connection", "close");
  2. or downgrade your HTTP version to 1.0. using either:
    • request.setVersion("HTTP/1.0");
    • or comment out the call to request.setVersion(); and rely on default behavior.
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top