java 如何对 servlet 进行单元测试?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4137484/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do I Unit Test a servlet?
提问by Amir Rachum
I have a servlet called Calculator
. It reads the parameters left
, right
and op
and returns by setting an attribute result
in the response.
我有一个名为Calculator
. 它读取参数left
,right
并op
通过result
在响应中设置一个属性来返回。
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?
对此进行单元测试的最简单方法是什么:基本上我想创建一个 HttpServletRequest,设置参数,然后检查响应 - 但我该怎么做呢?
Here's the servlet code (it's small and silly on purpose):
这是 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);
}
}
...
}
}
回答by erickson
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.
通常,程序的重要逻辑被分解到其他类中,这些类可在各种上下文中使用,而不是与 Servlet 引擎紧密耦合。这使 servlet 本身成为 Web 和您的应用程序之间的简单适配器。
This makes the program easier to test, and easier to reuse in other contexts like a desktop or mobile app.
这使程序更易于测试,并且更易于在桌面或移动应用程序等其他上下文中重用。
回答by marcelo
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:
您可以使用一些库。您是否在应用程序中使用 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());
...
回答by Todd
Check out ServletUnit. It's part of HttpUnit.
查看 ServletUnit。它是 HttpUnit 的一部分。
回答by madhurtanwani
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 :
不能说这是最好的方法:但是要对这样的简单 servlet(不使用转发、上下文等)进行单元测试,您可以简单地做的是:
- 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).
- 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. - Create an instance of the servlet -
new Calculator()
, keeping the required libs in the class path. Now call theservice
method on this instance. - 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.
- 使用任何模拟库创建模拟 HttpServletReqeust 和 HttpServletResponse 实例。更简单的是使用 RequestWrapper 和 ResponseWrapper 类(通过扩展 HttpServletReqeust 和 HttpServletResponse 类实现的简单自定义类)。
- 在这些模拟(或自定义)实例上设置某些属性 - 您要在每个测试用例中测试的参数 - 例如,
op=add
用于附加单元测试。如果您使用自定义类,您可以简单地在内部属性对象中设置它们。如果您正在使用模拟,那么设置期望就可以了。 - 创建 servlet - 的实例,
new Calculator()
在类路径中保留所需的库。现在调用service
此实例上的方法。 - 当调用返回时,从响应类中获取 o/p 并对其进行断言。由于响应类再次是自定义类或模拟版本,这应该很容易。
For mocking, a simply starting point would be EasyMock or Mockito (my fav)
对于模拟,一个简单的起点是 EasyMock 或 Mockito(我的最爱)
An example for the wrapper : http://tomcat.apache.org/tomcat-5.5-doc/servletapi/javax/servlet/http/HttpServletRequestWrapper.html
包装器示例:http: //tomcat.apache.org/tomcat-5.5-doc/servletapi/javax/servlet/http/HttpServletRequestWrapper.html
HTH
HTH
回答by Eugene Kuleshov
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.
通常,您应该从 Servlet 容器详细信息中抽象出您的业务逻辑。您可以使用Spring 测试包来模拟 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);
}
}