IgorShare Thoughts and Ideas

Consulting and Training

Mocking, embedded-Jetty and expectations for outgoing HTTP requests in Java

Posted by Igor Moochnick on 09/05/2008

If your classes in Java are executing outgoing HTTP calls it’s not easy to unit-test them. In many cases it requires to set-up separate web servers and deploy a test-verification code. I’m going to give you a way to do it in-line, just as you do it with any other unit-test.

In order to do this we’ll use embedded-Jetty. We’ll host Jetty inside the unit-testing framework.

For our example I’m going to use a TestNG unit-testing framework, but, as you can guess, you’re welcome to use any other you see fit.

1. First of all we need to initialize Jetty. We’re going to do it in @BeforeClass method:

private Server server;
private String returnUrl;

@BeforeClass
@Parameters({ "test-jetty-port" })
public void setUpJetty(@Optional("8123") int testPort) throws Exception
{
	server = new Server(testPort);

	Handler handler = new AbstractHandler()
	{
	    public void handle(String target, HttpServletRequest request, HttpServletResponse response, int dispatch)
	        throws IOException, ServletException
	    {
	        handleHttpRequest(target, request, response);
	    }
	};
	
	returnUrl = "http://localhost:" + Integer.toString(testPort) + "/test";
	
	server.setHandler(handler);

	server.start();
}

2. In order to consume all the incoming HTTP traffic we’re going to define a handler (we’re going to discuss other opportunities in the following posts). Note that the incoming HTTP traffic is stored inside the HttpTester parser class:

private HttpTester requestTest = new HttpTester();

private String getRequestString(HttpServletRequest request) throws Exception
{
	ServletInputStream reqz = request.getInputStream();
	int contentLen = request.getContentLength();
	if (contentLen == -1)
		return request.toString();
	
	byte[] buff = new byte[contentLen];
	int realLen = reqz.read(buff);
	
	Assert.assertEquals(realLen, contentLen, "Content length from parameter should be equal to the real content length");
	
	return request.toString() + new String(buff);
}

public void handleHttpRequest(String target, HttpServletRequest request, HttpServletResponse response)
{
	try
	{
		requestTest.parse( getRequestString(request) );
	}
	catch(Exception e)
	{
		Assert.fail("Failed to parse the incoming request.", e);
	}
	
    response.setContentType("text/html");
    response.setStatus(HttpServletResponse.SC_OK);
    ((Request)request).setHandled(true);
}

3. And this is how you can define your test fixture:

@Test
public void jobReport_returns_POST_reply() throws Exception
{
    String xml = "<xml>some-data-here</xml>";

    object-to-test.send_post(returnUrl, xml);
    
    Assert.assertEquals(requestTest.getMethod(), "POST");
    Assert.assertEquals(requestTest.getURI(), "/test");
    Assert.assertEquals(requestTest.getContent(), xml);
}

4. After all the tests are done, don’t forget to shutdown the Jetty server:

@AfterClass
public void tearDownJetty() throws Exception
{
	server.stop();
}
Advertisements

One Response to “Mocking, embedded-Jetty and expectations for outgoing HTTP requests in Java”

  1. Stefan Verhoeff said

    Thanks for this, just what I needed. This is what I used to add the dependencies to my Maven2 POM:

    org.mortbay.jetty
    jetty-embedded
    ${jetty.version}
    test

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

 
%d bloggers like this: