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

Java 如何对servlet进行单元测试?,java,unit-testing,jsp,servlets,junit,Java,Unit Testing,Jsp,Servlets,Junit,我有一个名为Calculator的servlet。它读取参数left、right和op,并通过在响应中设置属性result返回 单元测试的最简单方法是什么:基本上我想创建一个HttpServletRequest,设置参数,然后检查响应——但是我该如何做呢 以下是servlet代码(它很小,很傻): }查看ServletUnit。它是HttpUnit的一部分 有一些库可以使用。您是否在应用程序中使用Spring?如果是这样,则有一个spring应用程序(spring测试)包含MockHttpSer

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

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

以下是servlet代码(它很小,很傻):


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


有一些库可以使用。您是否在应用程序中使用Spring?如果是这样,则有一个spring应用程序(spring测试)包含MockHttpServletRequest。例如:

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

通常,您应该从Servlet容器细节中抽象业务逻辑。您可以使用模拟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);
   }
 }

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


这使得程序更容易测试,也更容易在桌面或移动应用程序等其他上下文中重用。

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

  • 使用任何模拟库创建模拟HttpServletReqeust和HttpServletResponse实例。更简单的方法是使用RequestWrapper和ResponseWrapper类(通过扩展HttpServletReqeust和HttpServletResponse类实现的简单自定义类)
  • 在这些模拟(或自定义)实例上,设置某些属性-每个测试用例中要测试的参数-例如,添加单元测试的
    op=add
    。如果您使用的是自定义类,只需在内部属性对象中设置它们即可。如果您使用的是模拟,那么设置就可以了
  • 创建servlet的实例-
    new Calculator()
    ,将所需的lib保留在类路径中。现在在此实例上调用
    服务
    方法
  • 当调用返回时,从响应类获取o/p并断言它。因为响应类还是一个自定义类或模拟版本,所以这应该很容易
  • 对于模仿,一个简单的起点是EasyMock或Mockito(我的最爱)

    包装器的一个示例:


    HTH

    您能展示servlet的一些代码吗?可能的重复代码您仍然需要能够测试“web和应用程序之间的简单适配器”。这属于集成测试的范畴,而不是单元测试。您将测试servlet与特定服务器引擎的集成,等等,而不是将其作为一个单元进行测试。
      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);
       }
     }