Home > testing > Unit Testing with HttpClient’s LocalTestServer

Unit Testing with HttpClient’s LocalTestServer

When unit testing code that uses HttpClient, it can get a bit tricky to not test against a active web server.  There are a couple of approaches to this to keep your tests at the unit level.

  1. Mock and inject HttpClient — While this is certainly possible and gives you complete control, it can take a lot of mocking and get tedious quite quickly.
  2. Use LocalTestServer from HttpClient — This is the point of this post and I will now explain.

Let’s take a look at the basic setup for getting this test server up.

Basic Setup

First, if you’re using Maven, you’ll need to bring in a new depedency.

  <dependency>
      <groupId>org.apache.httpcomponents</groupId>
      <artifactId>httpclient</artifactId>
      <version>4.0.1</version>
      <classifier>tests</classifier>
      <scope>test</scope>
  </dependency>

Next, you’ll need to setup your unit test with the test server.

public void setUp() {
    LocalTestServer server = new LocalTestServer(null, null);
    server.start();
}

That’s all it takes to get the server in place and started but it’s not very useful without some handlers.

Adding Handlers

To really get something worthwhile out of the server, you’ll want to register at least one handler.  Your handler must implement

org.apache.http.protocol.HttpRequestHandler

which has one really obvious method,

void handle(HttpRequest request, HttpResponse response, HttpContext context) throws HttpException, IOException;

Since we should be in a unit test, you can decide to either Mock this interface or create concrete classes that implement it.

Now that we have this spiffy way of controlling the response of the server, let’s see what it takes to register this handler with the server.

// do something to mock this or instantiate your own concrete class
HttpRequestHandler handler;

server.register("/someUrl/*", handler);

That’s all it takes to setup a local test server with at least 1 registered handler listening on /someUrl. For clarity, let’s take a look at the code all together.

public class MyUnitTest {
  private LocalTestServer server = null;

  @Mock 
  HttpRequestHandler handler;

  @Before
  public void setUp() {
    server = new LocalTestServer(null, null);
    server.register("/someUrl/*", handler);
    server.start();

    // report how to access the server
    String serverUrl = "http://" + server.getServiceHostName() + ":"
        + server.getServicePort();
    System.out.println("LocalTestServer available at " + serverUrl);
  }

  // do lots of testing!

  @After
  public void tearDown() {
    server.stop();
  }
}
About these ads
Categories: testing Tags: , ,
  1. April 15, 2010 at 11:24 am

    Carl,

    Thanks for this example – very helpful! I’m having a problem that maybe you can help me solve:

    I’ve set up a LocalTestServer in my Junit test, with a custom implementation of HttpRequestHandler;

    I’m posting to my LocalTestServer using a PostMethod with HttpClient;

    I’m setting a post parameter on that method before posting;

    When my HttpRequestHandler fields the request, my post parameter is not there.

    Any ideas as to what I’m doing wrong?

    Thanks
    Brian

    • April 15, 2010 at 2:27 pm

      The issue seems to be that HttpRequest in httpcore is for protocol-level requests; I was expecting to be able to use it like an HttpServletRequest.

      I used the following workaround:

      – create a test mode for the service I’m unit testing;

      – in test mode, append my post parameter to the request URI like this: “http://localhost:4565/my-path/myResource?myParam=”

      – then in my implementation of RequestHandler, I parse out the value and do what I need to with it.

      Not an ideal solution, but works for now.

      Has anyone else dealt with this issue?

      Best,
      Brian Y

      • thecarlhall
        May 24, 2010 at 10:28 am

        HttpClient does deal with protocol level commands and access. You might find a servlet test bit that could coupled with this to yield HttpServletRequest and HttpServletResponse.

  2. February 21, 2013 at 2:03 pm

    My project has a functioning dependency on HttpClient, but I can’t seem to reference the LocalTestServer… and some api’s (http://hc.apache.org/httpcomponents-client-ga/httpclient/apidocs/index.html?org/apache/http/client/package-summary.html) don’t include the localserver package, while some (http://hc.apache.org/httpcomponents-client-ga/httpclient/xref-test/index.html) do. What is the difference? How can I reference this class?

    • thecarlhall
      March 1, 2013 at 5:26 pm

      The difference there is that LocalTestServer is in src/test and not part of the main code. The apidocs show the code from src/main and the xref-test docs show you the tests. To reference this in your maven dependencies, be sure to include classifier=tests.

  1. December 25, 2013 at 7:52 pm

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

Join 270 other followers

%d bloggers like this: