在 測試JSP時,除了繼承ServletTestCase之 外,你還可以選擇繼承JspTestCase, 這方便你使用JSP的隱含物件(Implicit object)來進行相關測試。例如 測試 JSP 中的測試,也可以改為以下:
package test.cc.openhome;
import java.io.*;
import java.util.Arrays;
import java.util.List;
import org.apache.cactus.JspTestCase;
import org.apache.cactus.WebRequest;
import org.apache.cactus.WebResponse;
public class AddJSPTest extends JspTestCase {
static {
System.setProperty(
"cactus.contextURL", "http://localhost:8080/CactusExample");
}
// 測試沒有錯誤時的狀態,也就是第一次造訪JSP頁面時
public void testNoError() throws Exception {
pageContext.forward("add.jsp");
}
public void endNoError(WebResponse resp) throws Exception {
String html = getContent(resp);
assertTrue(!html.contains("<h1>新增書籤失敗</h1>"));
}
// 測試表單驗證失敗,回到JSP頁面時
public void testErrors() throws Exception {
List<String> errors = Arrays.asList("錯誤一", "錯誤二", "錯誤三");
request.setAttribute("errors", errors);
pageContext.forward("add.jsp");
}
public void endErrors(WebResponse resp) throws Exception {
String html = getContent(resp);
assertTrue(html.contains("<h1>新增書籤失敗</h1>"));
assertTrue(html.contains("<li>錯誤一</li>"));
assertTrue(html.contains("<li>錯誤二</li>"));
assertTrue(html.contains("<li>錯誤三</li>"));
}
// 測試表單驗證失敗,回到JSP頁面時測試請求參數回填
public void beginParameters(WebRequest req) throws Exception {
req.addParameter("url", "http://test");
// 客戶端是 UTF-8 編碼,Tomcat 預設使用 ISO-8859-1 處理請求參數
req.addParameter("title",
new String("測試".getBytes("UTF-8"), "ISO-8859-1"), "POST");
}
public void testParameters() throws Exception {
// 指定使用 UTF-8 處理請求參數
request.setCharacterEncoding("UTF-8");
pageContext.forward("add.jsp");
}
public void endParameters(WebResponse resp) throws Exception {
String html = getContent(resp);
assertTrue(html.contains("http://test"));
assertTrue(html.contains("測試"));
}
// 測試分類顯示
public void testCategories() throws Exception {
pageContext.setAttribute("bookmarkService",
new BookmarkService(), pageContext.APPLICATION_SCOPE);
pageContext.forward("add.jsp");
}
public void endCategories(WebResponse resp) throws Exception {
String html = getContent(resp);
assertTrue(html.contains("<option value=\"分類一\">分類一</option>"));
assertTrue(html.contains("<option value=\"分類二\">分類二</option>"));
assertTrue(html.contains("<option value=\"分類三\">分類三</option>"));
}
// 伺服端用UTF-8傳回
private String getContent(WebResponse resp) throws Exception {
InputStream input = resp.getInputStream();
StringWriter writer = new StringWriter();
byte[] data = new byte[2048];
int length = -1;
while((length = input.read(data)) != -1) {
writer.write(new String(data, 0, length, "UTF-8"));
}
input.close();
writer.close();
return writer.toString();
}
}
JspTestCase預 設的Redirect proxy網址是/JspRedirector, 你要將Cactus提供的jspRedirector.jsp複 製至Web應用程式中,並在web.xml中如下設定:
...
<servlet>
<servlet-name>JspRedirector</servlet-name>
<jsp-file>/jspRedirector.jsp</jsp-file>
</servlet>
<servlet-mapping>
<servlet-name>JspRedirector</servlet-name>
<url-pattern>/JspRedirector</url-pattern>
</servlet-mapping>
...
<servlet>
<servlet-name>JspRedirector</servlet-name>
<jsp-file>/jspRedirector.jsp</jsp-file>
</servlet>
<servlet-mapping>
<servlet-name>JspRedirector</servlet-name>
<url-pattern>/JspRedirector</url-pattern>
</servlet-mapping>
...
使用JspTestCase也 可以測試Taglib,例如在 處 理本體執行結果 中,測試ToUpperCaseTag需要 PageContext與BodyContent物件,雖然JspTestCase不直接提供BodyContent,但可以呼叫 pageContext.pushBody()來取得BodyContent。例如:
package test.cc.openhome;
import javax.servlet.jsp.tagext.BodyContent;
import javax.servlet.jsp.tagext.Tag;
import org.apache.cactus.JspTestCase;
import cc.openhome.ToUpperCaseTag;
public class ToUpperCaseTagTest extends JspTestCase {
static {
System.setProperty(
"cactus.contextURL", "http://localhost:8080/CactusExample");
}
public void testDoEndTag() throws Exception {
ToUpperCaseTag toUpperCaseTag = new ToUpperCaseTag();
toUpperCaseTag.setPageContext(pageContext);
// 內層標籤執行後的輸出結果
BodyContent innerBodyContent = pageContext.pushBody();
innerBodyContent.append("test");
toUpperCaseTag.setBodyContent(innerBodyContent);
// ToUpperCaseTag 的 doEndTag() 中,pageContext.getOut() 取得的物件
BodyContent toUpperCaseBodyOut = pageContext.pushBody();
assertEquals(Tag.EVAL_PAGE, toUpperCaseTag.doEndTag());
assertEquals("TEST", toUpperCaseBodyOut.getString());
}
}
由於Taglib擁有更多的生命周期狀態,這些本來都會是由容器維護,相對來說,測試Taglib必須了解容器作了哪些事,並在測試案例中加以模擬,必要 時,觀察JSP轉譯後的Servlet,了解容器對Taglib作了哪些處理,會有助於了解如何進行Taglib的測試。