我如何对servlet进行单元测试?

时间:2010-11-09 19:12:31

标签: java unit-testing jsp servlets junit

我有一个名为Calculator的servlet。它会读取参数leftrightop,并通过在响应中设置属性result来返回。

单元测试的最简单方法是什么:基本上我想创建一个HttpServletRequest,设置参数,然后检查响应 - 但我该怎么做?

这是servlet代码(它故意小而愚蠢):

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);
    }
}
...

}

5 个答案:

答案 0 :(得分:12)

通常,程序的重要逻辑被分解到其他类中,这些类可以在各种上下文中使用,而不是紧密耦合到Servlet引擎。这使servlet本身成为Web和应用程序之间的简单适配器。

这使程序更容易测试,并且更容易在桌面或移动应用程序等其他环境中重用。

答案 1 :(得分:10)

您可以使用一些库。您是否在应用程序中使用Spring http://www.springsource.org/?如果是这样,有一个包含MockHttpServletRequest的spring(spring-test)应用程序。例如:

@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());
            ...

答案 2 :(得分:1)

查看ServletUnit。它是HttpUnit的一部分。

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

答案 3 :(得分:1)

不能说这是最好的方法:但要对这样一个简单的servlet进行单元测试(一个不使用转发,上下文等......)你可以做的就是:

  1. 使用任何模拟库创建模拟HttpServletReqeust和HttpServletResponse实例。更简单的是使用RequestWrapper和ResponseWrapper类(通过扩展HttpServletReqeust和HttpServletResponse类实现的简单自定义类)。
  2. 在这些模拟(或自定义)实例上设置某些属性 - 您希望在每个测试用例中测试的参数 - 例如op=add进行加法单元测试。如果您使用自定义类,则只需在内部属性对象中设置它们即可。如果您正在使用模拟,那么设置期望就可以了。
  3. 创建servlet的实例 - new Calculator(),将所需的lib保留在类路径中。现在在此实例上调用service方法。
  4. 当调用返回时,从响应类中获取o / p并断言。由于响应类又是自定义类或模拟版本,因此应该很容易。
  5. 对于嘲笑,一个简单的起点是EasyMock或Mockito(我的收藏)

    包装器的示例:http://tomcat.apache.org/tomcat-5.5-doc/servletapi/javax/servlet/http/HttpServletRequestWrapper.html

    HTH

答案 4 :(得分:0)

通常,您应该从Servlet容器详细信息中抽象出业务逻辑。您可以使用Spring test package模拟ServletRequest,但模拟Servlet容器是个坏主意。因此,您应该在真实容器上运行系统测试,或者将您的逻辑从servlet移动到单独的bean中并单独测试它。

  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);
   }
 }