Writing Http Servlet Unit test using JMock2

Writing self-contained test-case related to JAVA Servlet API is something harder to the stuff you want to test. Image you have a servlet class and want to test it, the main problem is the servlet class couples with the servlet API in which you are not able to create them directly.

One of the traditional approach for this may need to bundle the J2EE server (usually tomcat) in your test-case, start the server programmatically, and stimulate the request/response lifecycle. This is obviously not a good approach and you may take several day in order to work properly ONLY in your machine.

To erase the complexity of test-case development, we can use a popular mocking framework called JMock2. It is simple yet robust framework that applies declarative mocking statement so that you can understanding everything in just few minutes.

Let start ! I will demonstrate a short example of mocking the input stream and output stream of servlet request and response.

package org.twiky.sample;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;

import org.jmock.Expectations;
import org.jmock.Mockery;
import org.junit.Test;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.ServletOutputStream;

/**
 * This is simple JUnit4 test-case for demonstrating the mocking capabilities.
 *
 * @author twinsen.tsang
 */
public class JMockHttpServlet {

	/* JMock2 context */
	private Mockery mockContext = new Mockery(); 

	@Test
	public void testMock() throws Throwable {
		final HttpServletRequest  mkRequest  = mockContext.mock(HttpServletRequest.class);
		final HttpServletResponse mkResponse = mockContext.mock(HttpServletResponse.class);
		final ServletOutputStream sos = new ServletOutputStream(){
			@Override
			public void write(int c) throws IOException {
				System.out.print((char)c);
			}
		};

		mockContext.checking(new Expectations(){
			{
				allowing (mkRequest).getInputStream();   will(returnValue(new ByteArrayInputStream("Test Mock".getBytes())));
				allowing (mkResponse).getOutputStream(); will(returnValue(sos));
			}
		});

		// Try do something with the mocking context
		this.process(mkRequest, mkResponse);

		// Check whether all expectations are satisfied.
		mockContext.assertIsSatisfied();
	}

	/**
	 * Do something with the HTTP mocking request and response.
	 *
	 * @param req The HTTP servlet request.
	 * @param resp The HTTP servlet response.
	 * @throws IOException
	 */
	public void process(HttpServletRequest req, HttpServletResponse resp) throws IOException {
		resp.getOutputStream().write("Test Mock output".getBytes());
	}
}

The core element of JMock2 is called Mockery, which serves as the context object for storing the mocking object and expectation you want to make with the mocking objects. Expectation is the sentence you expect from the input to the stuff you want to test.

In the above example, servlet request/response object are mocked through the below code:

 final HttpServletRequest  mkRequest  = mockContext.mock(HttpServletRequest.class);
 final HttpServletResponse mkResponse = mockContext.mock(HttpServletResponse.class);

Invoking the method Mockery.mock(class) to mock the interface/abstract class. The mockery will return a mocking object conforming the interface/abstract class passing in the argument. THAT IT ! You have created fake servlet request and servlert response for your test-case. Now let add some expectation that we want our request/response to do with us.

 mockContext.checking(new Expectations(){
  {
   allowing (mkRequest).getInputStream();   will(returnValue(new ByteArrayInputStream("Test Mock".getBytes())));
   allowing (mkResponse).getOutputStream(); will(returnValue(sos));
  }
 });

Each expectation is just like a english statement. In the above example, i expected the servlet request should able to return a input stream with the content "Test Mock" and the response should return a servlet output stream which write any content to the system.out (see full source in the above).

To be continued...

Reference:

  1. JMock2 cheat sheet http://www.jmock.org/cheat-sheet.html
  2. JMock2 cookbook http://www.jmock.org/cookbook.html
 
About these ads
Posted in JAVA, Test Driven. Tags: . 1 Comment »

One Response to “Writing Http Servlet Unit test using JMock2”

  1. Erem Says:

    Hey thanks so much for this tutorial. It would have taken hours to figure out without your excellent documentation.


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.

%d bloggers like this: