11 февр. 2012 г.

Small HTTP web server for functional testing

Some time ago I needed a webserver for functional testing of my java HTTP client library.
I looked for a web server which satisfy following conditions:

1. Embeddable - the main condition.
2. Easy to integrate with unit testing frameworks
3. Small amount of code and config to setup server
4. Quick startup and shutdown.
5. Small size of the library.

The first candidate which satisfy main condition is Jetty.
It is cool but it doesn't satisfy all other my conditions.

Next candidate is com.sun.net.httpserver.HttpServer which is embedded into JDK 1.6 and higher.
It is excellent candidate for my needs, so i decided to use it.
I've implemented some kind of abstraction layer over HttpServer to fully satisfify 2-nd and 3-d conditions and as a result i wrote very small library which i called anhttpserver (Another HTTP Server)

here is basic usage example of that library:

import anhttpserver.ByteArrayHandlerAdapter;
import anhttpserver.DefaultSimpleHttpServer;
import anhttpserver.HttpRequestContext;
import anhttpserver.SimpleHttpServer;


import java.io.IOException;

public class SimpleServer {

    public static void main(String[] args) throws Exception {
        SimpleHttpServer server = new DefaultSimpleHttpServer();
        server.start();
        server.addHandler("/index", new ByteArrayHandlerAdapter() {
            public byte[] getResponseAsByteArray(HttpRequestContext httpRequestContext) throws IOException {
                return "Hello world".getBytes();
            }
        });
    }
}

Now point your favorite browser to http://localhost:8000/index - you should see "Hello world".

Isn't it easy?


Let's write basic JUnit test which will show, how easy to write functional tests using this library:

import anhttpserver.ByteArrayHandlerAdapter;
import anhttpserver.DefaultSimpleHttpServer;
import anhttpserver.HttpRequestContext;
import anhttpserver.SimpleHttpServer;
import org.apache.commons.io.IOUtils;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;

import static org.junit.Assert.assertEquals;

public class SimpleTest {

    private SimpleHttpServer server;

    @Before
    public void init() {
        server = new DefaultSimpleHttpServer();
        server.start();
    }


    @After
    public void finish() {
        server.stop();
    }

    //In our example this is function we test,
    //in your case most probablt it will be some other entity
    private String getResult(String urlString) throws Exception {
        URLConnection connection = (new URL(urlString)).openConnection();
        InputStream is = connection.getInputStream();
        String result = IOUtils.toString(is);
        is.close();
        return result;
    }


    @Test
    public void basicServerTest() throws Exception {
        server.addHandler("/", new ByteArrayHandlerAdapter() {
            @Override
            public byte[] getResponseAsByteArray(HttpRequestContext httpRequestContext) throws IOException {
                String response = "Hello world!";
                return response.getBytes();
            }
        });

        assertEquals("Hello world!", getResult("http://localhost:8000"));
    }
}

More examples of using anhttpserver library you can see in source code of anhttpserver and anhttpclient projects which are open source and released under the MIT license.

Also there is one non usual example of usage of this library - jstreamserver (HTTP Live Streaming for IPad and IPhone).

Here i used anhttpclient not for functional testing but as an HTTP server.
For sure i do not recommend to use it in such way - i didn't perform any stability and performance testing, but this example is proof of the viability of anhttpserver.

You can download sources of anhttpserver here: https://github.com/sprilukin/anhttpserver

Thank you for attention,
Comments are welcome.




Комментариев нет:

Отправить комментарий