【问题标题】:How do I Unit Test a servlet?如何对 servlet 进行单元测试?
【发布时间】:2010-11-09 19:12:30
【问题描述】:

我有一个名为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);
    }
}
...

}

【问题讨论】:

标签: java unit-testing jsp servlets junit


【解决方案1】:

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

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

【讨论】:

  • 您仍然需要能够测试“Web 和您的应用程序之间的简单适配器”..
  • 这属于集成测试的范畴,而不是单元测试。您将测试 servet 与特定服务器引擎等的集成,而不是将其作为一个单元进行测试。
【解决方案2】:

您可以使用一些库。你在你的应用程序中使用 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());
            ...

【讨论】:

    【解决方案3】:

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

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

    【讨论】:

      【解决方案4】:

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

      1. 使用任何模拟库创建模拟 HttpServletReqeust 和 HttpServletResponse 实例。更简单的是使用 RequestWrapper 和 ResponseWrapper 类(通过扩展 HttpServletReqeust 和 HttpServletResponse 类实现的简单自定义类)。
      2. 在这些模拟(或自定义)实例上设置某些属性 - 您要在每个测试用例中测试的参数 - 例如op=add 用于添加单元测试。如果您使用自定义类,您可以简单地在内部属性对象中设置它们。如果您使用的是模拟,那么设置期望就可以了。
      3. 创建 servlet 的实例 - new Calculator(),将所需的库保存在类路径中。现在在这个实例上调用service 方法。
      4. 当调用返回时,从响应类中获取 o/p 并声明它。由于响应类又是自定义类或模拟版本,这应该很容易。

      对于模拟,一个简单的起点是 EasyMock 或 Mockito(我的最爱)

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

      HTH

      【讨论】:

        【解决方案5】:

        通常,您应该从 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);
           }
         }
        

        【讨论】:

          猜你喜欢
          • 2010-09-10
          • 1970-01-01
          • 1970-01-01
          • 2012-01-08
          • 2019-11-02
          • 1970-01-01
          • 1970-01-01
          • 2012-12-20
          • 2013-09-30
          相关资源
          最近更新 更多