如何使用 JUnit 测试我的 servlet
我已经使用 Java Servlet 创建了一个 Web 系统,现在想要进行 JUnit 测试。我的 dataManager 只是将其提交到数据库的一段基本代码。您将如何使用 JUnit 测试 Servlet?
我的代码示例允许用户注册/注册,该代码示例是通过 AJAX 从我的主页提交的:
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException{
// Get parameters
String userName = request.getParameter("username");
String password = request.getParameter("password");
String name = request.getParameter("name");
try {
// Load the database driver
Class.forName("com.mysql.jdbc.Driver");
//pass reg details to datamanager
dataManager = new DataManager();
//store result as string
String result = dataManager.register(userName, password, name);
//set response to html + no cache
response.setContentType("text/html");
response.setHeader("Cache-Control", "no-cache");
//send response with register result
response.getWriter().write(result);
} catch(Exception e){
System.out.println("Exception is :" + e);
}
}
I have created a web system using Java Servlets and now want to make JUnit testing. My dataManager
is just a basic piece of code that submits it to the database. How would you test a Servlet with JUnit?
My code example that allows a user to register/sign up, which is submitted from my main page via AJAX:
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException{
// Get parameters
String userName = request.getParameter("username");
String password = request.getParameter("password");
String name = request.getParameter("name");
try {
// Load the database driver
Class.forName("com.mysql.jdbc.Driver");
//pass reg details to datamanager
dataManager = new DataManager();
//store result as string
String result = dataManager.register(userName, password, name);
//set response to html + no cache
response.setContentType("text/html");
response.setHeader("Cache-Control", "no-cache");
//send response with register result
response.getWriter().write(result);
} catch(Exception e){
System.out.println("Exception is :" + e);
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(9)
您可以使用 Mockito 来让模拟返回正确的参数,验证它们确实被调用(可以选择指定次数),写下“结果”并验证其是否正确。
You can do this using Mockito to have the mock return the correct params, verify they were indeed called (optionally specify number of times), write the 'result' and verify it's correct.
首先,在真实的应用程序中,您永远不会在 servlet 中获取数据库连接信息;您可以在您的应用程序服务器中配置它。
然而,有一些方法可以在不运行容器的情况下测试 Servlet。一种是使用模拟对象。 Spring 为 HttpServletRequest、HttpServletResponse、HttpServletSession 等提供了一组非常有用的模拟:
http://static.springsource.org/spring/docs/3.0.x/api/org/springframework/mock/web/package-summary.html
使用这些模拟,您可以测试 ?
如果用户名不在请求中会发生什么
如果请求中包含用户名,会发生什么情况?
等等
然后你可以做类似的事情:
First off, in a real application, you would never get database connection info in a servlet; you would configure it in your app server.
There are ways, however, of testing Servlets without having a container running. One is to use mock objects. Spring provides a set of very useful mocks for things like HttpServletRequest, HttpServletResponse, HttpServletSession, etc:
http://static.springsource.org/spring/docs/3.0.x/api/org/springframework/mock/web/package-summary.html
Using these mocks, you could test things like
What happens if username is not in the request?
What happens if username is in the request?
etc
You could then do stuff like:
我发现 Selenium 测试对于集成或功能(端到端)测试更有用。我正在尝试使用org.springframework.mock.web,但我还没有走得太远。我正在附加一个带有 jMock 测试套件的示例控制器。
首先,控制器:
接下来,测试:
我希望这可能有所帮助。
I find Selenium tests more useful with integration or functional (end-to-end) testing. I am working with trying to use org.springframework.mock.web, but I am not very far along. I am attaching a sample controller with a jMock test suite.
First, the Controller:
Next, the test:
I hope this might help.
2018 年 2 月更新:OpenBrace Limited 已关闭,不再支持其 ObMimic 产品。
这是另一种选择,使用 OpenBrace 的 ObMimic Servlet API 测试替身库(声明:我是它的开发人员)。
注意:
每个“mimic”都有一个用于其逻辑状态的“mimicState”对象。这提供了 Servlet API 方法与模拟内部状态的配置和检查之间的明显区别。
您可能会对 Content-Type 的检查包括“charset=ISO-8859-1”感到惊讶。然而,对于给定的“doPost”代码,这是根据 Servlet API Javadoc、HttpServletResponse 自己的 getContentType 方法以及在 Glassfish 3 上生成的实际 Content-Type 标头。如果使用普通的模拟对象和您的应用程序,您可能不会意识到这一点。自己对 API 行为的期望。在这种情况下,这可能并不重要,但在更复杂的情况下,这是一种意料之外的 API 行为,可能会带来一点嘲笑!
我使用了
response.getMimicState().getContentType()
作为检查 Content-Type 并说明上述观点的最简单方法,但您确实可以检查“text/html”如果您愿意的话,它自己的(使用response.getMimicState().getContentTypeMimeType())。检查 Content-Type 标头的方法与检查 Cache-Control 标头的方法相同。在此示例中,响应内容被检查为字符数据(使用 Writer 的编码)。我们还可以检查是否使用了响应的 Writer 而不是其 OutputStream(使用response.getMimicState().isWritingCharacterContent()),但我认为我们只关心结果输出,并且不关心什么 API 调用产生了它(尽管也可以检查......)。还可以以字节形式检索响应的正文内容,检查 Writer/OutputStream 等的详细状态。
的完整详细信息可以在 OpenBrace 网站。或者有任何疑问也可以联系我(联系方式见网站)。
Updated Feb 2018: OpenBrace Limited has closed down, and its ObMimic product is no longer supported.
Here's another alternative, using OpenBrace's ObMimic library of Servlet API test-doubles (disclosure: I'm its developer).
Notes:
Each "mimic" has a "mimicState" object for its logical state. This provides a clear distinction between the Servlet API methods and the configuration and inspection of the mimic's internal state.
You might be surprised that the check of Content-Type includes "charset=ISO-8859-1". However, for the given "doPost" code this is as per the Servlet API Javadoc, and the HttpServletResponse's own getContentType method, and the actual Content-Type header produced on e.g. Glassfish 3. You might not realise this if using normal mock objects and your own expectations of the API's behaviour. In this case it probably doesn't matter, but in more complex cases this is the sort of unanticipated API behaviour that can make a bit of a mockery of mocks!
I've used
response.getMimicState().getContentType()
as the simplest way to check Content-Type and illustrate the above point, but you could indeed check for "text/html" on its own if you wanted (usingresponse.getMimicState().getContentTypeMimeType()
). Checking the Content-Type header the same way as for the Cache-Control header also works.For this example the response content is checked as character data (with this using the Writer's encoding). We could also check that the response's Writer was used rather than its OutputStream (using
response.getMimicState().isWritingCharacterContent()
), but I've taken it that we're only concerned with the resulting output, and don't care what API calls produced it (though that could be checked too...). It's also possible to retrieve the response's body content as bytes, examine the detailed state of the Writer/OutputStream etc.There are full details of ObMimic and a free download at the OpenBrace website. Or you can contact me if you have any questions (contact details are on the website).
编辑:仙人掌现在是一个死项目:http:// attic.apache.org/projects/jakarta-cactus.html
您可能想看看仙人掌。
http://jakarta.apache.org/cactus/
EDIT: Cactus is now a dead project: http://attic.apache.org/projects/jakarta-cactus.html
You may want to look at cactus.
http://jakarta.apache.org/cactus/
另一种方法是创建一个嵌入式服务器来“托管”您的 servlet,允许您使用旨在调用实际服务器的库编写对它的调用(这种方法的有用性在某种程度上取决于您如何容易地使“合法”编程化)对服务器的调用 - 我正在测试 JMS(Java 消息服务)访问点,该访问点有大量客户端)。
您可以选择几条不同的路线 - 通常的两条路线是 tomcat 和 jetty。
警告:选择要嵌入的服务器时需要注意的是您正在使用的 servlet-api 的版本(提供 HttpServletRequest 等类的库)。如果您使用的是 2.5,我发现 Jetty 6.x 运行良好(这是我将在下面给出的示例)。如果您使用 servlet-api 3.0,tomcat-7 嵌入的东西似乎是一个不错的选择,但是我不得不放弃使用它的尝试,因为我测试的应用程序使用 servlet-api 2.5。在尝试配置或启动服务器时,尝试混合两者将导致 NoSuchMethod 和其他此类异常。
您可以像这样设置这样的服务器(Jetty 6.1.26,servlet-api 2.5):
Another approach would be to create an embedded server to "host" your servlet, allowing you to write calls against it with libraries meant to make calls to actual servers (the usefulness of this approach somewhat depends on how easily you can make "legitimate" programatic calls to the server - I was testing a JMS (Java Messaging Service) access point, for which clients abound).
There are a couple of different routes you can go - the usual two are tomcat and jetty.
Warning: something to be mindful of when choosing the server to embed is the version of servlet-api you are using (the library which provides classes like HttpServletRequest). If you are using 2.5, I found Jetty 6.x to work well (which is the example I'll give below). If you're using servlet-api 3.0, the tomcat-7 embedded stuff seems to be a good option, however I had to abandon my attempt to use it, as the application I was testing used servlet-api 2.5. Trying to mix the two will result in NoSuchMethod and other such exceptions when attempting to configure or start the server.
You can set up such a server like this (Jetty 6.1.26, servlet-api 2.5):
首先,您可能应该对此进行一些重构,以便不会在 doPost 代码中创建 DataManager。您应该尝试依赖注入来获取实例。 (请观看 Guice 视频,了解 DI 的精彩介绍。)如果您被告知要开始对所有内容进行单元测试,那么 DI 是必须具备的。
注入依赖项后,您可以单独测试您的类。
要实际测试 servlet,还有其他较旧的线程已经讨论过这个问题。请尝试此处 和此处。
First you should probably refactor this a bit so that the DataManager is not created in the doPost code.. you should try Dependency Injection to get an instance. (See the Guice video for a nice intro to DI.). If you're being told to start unit testing everything, then DI is a must-have.
Once your dependencies are injected you can test your class in isolation.
To actually test the servlet, there are other older threads that have discussed this.. try here and here.
使用 Selenium 进行基于 Web 的单元测试。有一个名为 Selenium IDE 的 Firefox 插件,它可以记录网页上的操作并导出到 JUnit 测试用例,该测试用例使用Selenium RC 运行测试服务器。
Use Selenium for webbased unit tests. There's a Firefox plugin called Selenium IDE which can record actions on the webpage and export to JUnit testcases which uses Selenium RC to run the test server.