Answers:
我认为没有测试JSP的好方法,主要是因为JSP是在单元测试成为开发重点之前开发的。
罗伯特·马丁(Robert Martin)几年前写了一篇文章,内容涉及黑客JSP编译器,以便您可以直接进行基于非容器的单元测试。他的想法很好,但是在下一个TomCat主要版本中就被打破了。发生了太多的魔术。
我不同意“只要不添加代码,您就不需要测试它”的想法。显然,您不应该将代码放入JSP中。但是,尽管如此,复杂的UI仍将经常具有可进行有益的单元测试的显示逻辑。
考虑以下示例:
<c:choose>
<c:when test="${mydto.showAdminMenu}">
The admin menu....
</c:when>
<c:otherwise>
Something completely different
</c:otherwise>
</c:choose>
这段代码已经被充分考虑:决定我们是否显示管理菜单的逻辑不在视图中。尽管如此,如果有一种简单的方法来对JSP进行单元测试,那么我们可以编写一个测试来表明我们想要的行为实际上已经出现,并且可以保护我们免受页面更改的影响,该页面在需要时意外地使管理菜单可见不是。
存在一个程序(供您使用的任何应用程序服务器使用),该程序可将.jsp文件编译为.java文件。例如,sun / oracle版本jspc。
一旦有了由.jsp转换生成的.java(您甚至可以考虑在构建过程中使用它-预编译jsp以提高性能),然后可以对其进行测试通过模拟请求并验证响应是否符合您的期望。
(编辑示例:)
关键方法是_jspService(HttpServletRequest, HttpServletResponse)
方法。
一个简单的hello world jsp:
<html>
<head>
<title>Hello world</title>
</head>
<body>
<h1>Hello world</h1>
Today is: <%= new java.util.Date().toString() %>
</body>
</html>
(test.jsp位于名为“ webapp”的目录中,并且也位于“ out”目录中)。使用命令编译时,jspc -v -d out -compile -uriroot webapp/ test.jsp
会将名为的文件放入out目录中test_jsp.java
。该文件包含在其中(以及相当多的其他配置设置):
public void _jspService(HttpServletRequest request, HttpServletResponse response)
throws java.io.IOException, ServletException {
PageContext pageContext = null;
HttpSession session = null;
ServletContext application = null;
ServletConfig config = null;
JspWriter out = null;
Object page = this;
JspWriter _jspx_out = null;
PageContext _jspx_page_context = null;
try {
response.setContentType("text/html");
pageContext = _jspxFactory.getPageContext(this, request, response,
null, true, 8192, true);
_jspx_page_context = pageContext;
application = pageContext.getServletContext();
config = pageContext.getServletConfig();
session = pageContext.getSession();
out = pageContext.getOut();
_jspx_out = out;
out.write("<html>\n\t<head>\n\t\t<title>Hello world</title>\n\t</head>\n\t<body>\n\t
\t<h1>Hello world</h1>\n\t\tToday is: ");
out.print( new java.util.Date().toString() );
out.write("\n\t</body>\n</html>\n\n");
} catch (Throwable t) {
if (!(t instanceof SkipPageException)){
out = _jspx_out;
if (out != null && out.getBufferSize() != 0)
try { out.clearBuffer(); } catch (java.io.IOException e) {}
if (_jspx_page_context != null) _jspx_page_context.handlePageException(t);
}
} finally {
_jspxFactory.releasePageContext(_jspx_page_context);
}
}
}
在这一点上,检查以确保JspWriter是用write或print调用的,并且调用的内容就是您所期望的。
综上所述,在理想的世界中,jsp内不应包含任何逻辑-这种逻辑可以在控制器中或在使用其他技术测试过的taglib中。
您也可以考虑使用HTTP单元测试框架,例如HTTPUnit | http://httpunit.sourceforge.net/。
另一个重要的点是将您的应用程序关注点分开。
例如,使用TDD(http://en.wikipedia.org/wiki/Test-driven_development)之类的技术,您将设计可测试性的类型。
JSP中使用的类型将在特定的单元测试中进行测试。如果不可能,则应模拟用户->浏览器交互(同样,HTTPUnit或类似工具)。