Using Sun Java 6 httpserver to write a functional HTTP test

Source: Internet
Author: User
Tags readline response code standalone web server
forces

At work, we recently had the need to perform functional testing of a custom client that used HTTP as a transport. This isn ' t strictly unit testing since we ' re conducting actual HTTP over a socket & port instead of stubbing out or mo cking the server, but in this case, is the only real way to test the client.

I could ' ve fired up a standalone Web server and used that, but decided the it for a against of couple.

I wanted to have the server respond in a specific way to a particular client request. For example, if the request is for Get/1234.xml I might want to respond with an HTTP and a XML response body. Another request for Get/0.xml might return of HTTP 404 instead.

To do using, say, a Servlet container would mean writing multiple servlets (mapped to various request URI) or a ' rich ' Servlet with additional complexity. I didn ' t want to have to write tests to test my test scaffolding!

Secondly, a standalone server would have to is started and stopped of our outside standard process (U Sing Maven). The other people wouldn ' t is able to run the tests successfully without has the test server up as a.

Clearly, the best way to go is embedded HTTP server, which would allow us to provide specific responses Tailore D for each unit test.

As luck would have it, it turns out of that Sun's Java 6 implementation comes with a lightweight HTTP server APIs built in. Read on as I demonstrate the basic use of Sun's HTTP server classes to write a functional test.

HTTP Server in a box

The heart of our test solution involves taking advantage to the lightweight HTTP server API included in Sun ' s Java 6 imple Mentation. This is the since this isn ' t part of the Java core APIs This package may is available on all Java platforms. If It is a problem, your might be better off using another embedded HTTP server such as Jetty.

The class itself is com.sun.net.httpserver.HttpServer, and here's how to use it in a nutshell:create the server Create a Server context and register a request handler Start the server perform your test Stop the server, and Verify/assert your E xpected behavior

Now let's look at the each step in detail with corresponding code. Create the server

We Create an Httpserver using Httpserver.create (). To specify a port, we are need to pass in a inetsocketaddress:inetsocketaddress address = new Inetsocketaddress (8000) ;
Httpserver httpserver = Httpserver. Create (address, 0);

The second parameter to Httpserver.create () was the ' backlog ', "the maximum number of queued incoming to connections On the listening socket. Since that doesn ' t really affect us, we can just pass in a 0 and a system default value is used. creating and registering a request handler

Now we have the meat of actually stubbing our server's behavior by creating and registering a request handler. Httpserver provides the Createcontext (String path, HttpHandler handler) method to did just that.

Now, HttpHandler are an interface which declares one method:handle (Httpexchange)

Obviously, Httpexchange is the class we need to work with when responding to HTTP requests. Let's look at some code and I ' ll explain what it does afterwards:httphandler handler = new HttpHandler () {

public void handle (Httpexchange Exchange) throws IOException {
byte[] Response = "<?xml version=\" 1.0\ ">\n<resource id=\" 1234\ "name=\" test\ "/>\n". GetBytes ();
Exchange.sendresponseheaders (HTTPURLCONNECTION.HTTP_OK,
Response.length);
Exchange.getresponsebody (). write (response);
Exchange.close ();
}
};

Basically:we convert our response string into a byte array. We send an HTTP [OK] along with the number of bytes we are about to send as the response body. We then write out the bytes of our response body and then close the Httpexchange. The complete Httpexchange life cycle are detailed in its API documentation.

We create a context for the URI we ' re interested in, passing in our newly created HttpHandler, then start the server: Httpserver. Createcontext ("/1234.xml", Handler);
Httpserver. Start ();

At I, an actual HTTP server'll start running in a background thread ready to respond to requests. Let ' s exercise our client code:url url = new URL ("Http://localhost:8000/1234.xml");
URLConnection conn = URL. OpenConnection ();
BufferedReader in = new BufferedReader (New InputStreamReader (Conn. getInputStream ()));
Assertequals ("<?xml version=\" 1.0\ "?>", in. readLine ());
Assertequals ("<resource id=\" 1234\ "name=\" test\ "/>", in. readLine ());

Our client code connects to our servers, retrieves the associated URI, then, using a bufferedreader reads in lines from the Input stream. We make a few JUnit assertions on what we received.

The only thing-to-do-to-stop our httpserver:httpserver. Stop (0);

The parameter is the number of seconds (note:not milliseconds) to blocks to a wait for our httpserver to shutdown properly. Since We know we ' re not serving any other requests, we can safely tell our httpserver to shut down immediately. At a glance

Here's our functional Test at a glance://Create the Httpserver
Inetsocketaddress address = new Inetsocketaddress (8000);
Httpserver httpserver = Httpserver. Create (address, 0);

Create and register our handler
HttpHandler handler = new HttpHandler () {

public void handle (Httpexchange Exchange) throws IOException {
byte[] Response = "<?xml version=\" 1.0\ ">\n<resource id=\" 1234\ "name=\" test\ "/>\n". GetBytes ();
Exchange.sendresponseheaders (HTTPURLCONNECTION.HTTP_OK,
Response.length);
Exchange.getresponsebody (). write (response);
Exchange.close ();
}
};
Httpserver.createcontext ("/1234.xml", Handler);

Start the server
Httpserver.start ();

Verify our client code
URL url = new URL ("Http://localhost:8000/1234.xml");
URLConnection conn = Url.openconnection ();
BufferedReader in = new BufferedReader (New InputStreamReader (Conn.getinputstream ()));
Assertequals ("<?xml version=\" 1.0\ "?>", In.readline ());
Assertequals ("<resource id=\" 1234\ "name=\" test\ "/>", In.readline ());

Stop the server
Httpserver.stop (0);

While functional, I find the above code rather verbose. If I want to write more HTTP tests, I certainly don ' t want to keep repeating the myself going (); ... httpserver.stop (0); I especially find it tedious to have to compute the length of the HTTP response body beforehand, then send it along with O ur HTTP response code before writing out the actual body.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.