开发者

How do I Unit Test a servlet?

I have a servlet called Calculator. It reads the pa开发者_如何转开发rameters left, right and op and returns by setting an attribute result in the response.

What is the easiest way to unit test this: basically I want to create an HttpServletRequest, set the parameters, and then checking the response - but how do I do that?

Here's the servlet code (it's small and silly on purpose):

public class Calculator extends javax.servlet.http.HttpServlet implements javax.servlet.Servlet {
public Calculator() {
    super();
}       
protected void doGet(HttpServletRequest request, HttpServletResponse response) 
    throws ServletException, IOException {
}   
protected void doPost(HttpServletRequest request, HttpServletResponse response) 
    throws ServletException, IOException {
    Integer left = Integer.valueOf(request.getParameter("left"));
    Integer right = Integer.valueOf(request.getParameter("right"));
    Integer result = 0;
    String op = request.getParameter("operator");
    if ("add".equals(op)) result = this.opAdd(left, right);
    if ("subtract".equals(op)) result = this.opSub(left, right);
    if ("multiply".equals(op)) result = this.opMul(left, right);
    if ("power".equals(op)) result = this.opPow(left, right);
    if ("divide".equals(op)) result = this.opDiv(left, right);
    if ("modulo".equals(op)) result = this.opMod(left, right);

    request.setAttribute("result", result); // It'll be available as ${sum}.
    request.getRequestDispatcher("index.jsp").forward(request, response);
    }
}
...

}


Often, the important logic of a program is factored out into other classes, that are usable in a variety of contexts, instead of being tightly coupled to a Servlet Engine. This leaves the servlet itself as a simple adapter between the web and your application.

This makes the program easier to test, and easier to reuse in other contexts like a desktop or mobile app.


There are a few libraries out there that you can use. Are you using Spring http://www.springsource.org/ in your application? If so, there is one application for spring (spring-test) that contains MockHttpServletRequest. For example:

@Test
public void shouldReturnAValidaRedirectionMessage() {
    MockHttpServletRequest request = new MockHttpServletRequest();
    request.addParameter("op", "addition");
    request.addParameter("left", "1");
    request.addParameter("right", "5");

    CalculatorServlet servlet = new CalculatorServlet();
    Operation operation = servlet.getOperation(request);
    assertNotNull(operation);
    assertEquals(ADDITION, operation.getOperationType());
            ...


Check out ServletUnit. It's part of HttpUnit.

http://httpunit.sourceforge.net/doc/servletunit-intro.html


Can't say this is the best method to do so : but to unit test a simple servlet like that (one not using forwards, context etc..) what you could simply do is :

  1. Create mock HttpServletReqeust and HttpServletResponse instances using any mocking library. Even simpler would be using RequestWrapper and ResponseWrapper classes (simple custom classes implemented by extending the HttpServletReqeust and HttpServletResponse classes).
  2. On these mock (or custom) instances set certain properties - the parameters you want to test against in each test case - e.g. op=add for a addition unit test. If you are using custom classes, you can simply set them in an internal properties object. If you are using mocks, then settings expectations would do.
  3. Create an instance of the servlet - new Calculator(), keeping the required libs in the class path. Now call the service method on this instance.
  4. When the call returns, get the o/p from the response class and assert it. Since the response class is again a custom class or a mocked version, this should be easy.

For mocking, a simply starting point would be EasyMock or Mockito (my fav)

An example for the wrapper : http://tomcat.apache.org/tomcat-5.5-doc/servletapi/javax/servlet/http/HttpServletRequestWrapper.html

HTH


Generally you should abstract your business logic from Servlet container details. You can mock ServletRequest using Spring test package, but it would be a bad idea to simulate Servlet container. So, you should either run system tests on a real container or move your logic from servlet into a separate bean and test it in isolation.

  public class Calculator {
    public Integer calculate(Integer left, Integer right, String op) {
      Integer result = 0;
      if ("add".equals(op)) result = this.opAdd(left, right);
      if ("subtract".equals(op)) result = this.opSub(left, right);
      if ("multiply".equals(op)) result = this.opMul(left, right);
      if ("power".equals(op)) result = this.opPow(left, right);
      if ("divide".equals(op)) result = this.opDiv(left, right);
      if ("modulo".equals(op)) result = this.opMod(left, right);
      return result;
    }
  }


  public class CalculatorServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) 
        throws ServletException, IOException {
     Integer left = Integer.valueOf(request.getParameter("left"));
     Integer right = Integer.valueOf(request.getParameter("right"));
     String op = request.getParameter("operator");
     Integer result = calculator.calculate(left, right, op);
     request.setAttribute("result", result); // It'll be available as ${sum}.
     request.getRequestDispatcher("index.jsp").forward(request, response);
   }
 }
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜