使用Cactus对taglib进行单元测试
下图描述了使用Cactus对标记库的一个标记进行单元测试的过程。(图片链接)
1.Cactus对象初始化测试类,该类必须派生自JspTestCase类,测试标记时所需要的任何HTTP参数,都需要在beginXXX方法中进行配置。例如,如果某标记从Http参数提取信息,那么你需要在beginXXX方法中定义该参数。
2.在内部,Cactus的JspTestCase类调用Cactus JSP Redirector(本身也是一个JSP)。JSP Redirector负责在服务器端初始化JspTestCase类,传送JSP隐式对象(主要是PageContext对象)给它。然后,再调用testXXX方法。
3.在testXXX方法中,编写代码对JSP标记进行单元测试。测试一个标记的典型步骤为:用new 对象初始化该标记,调用setPageContext,来设置PageContext,调用测试方法进行测试,然后执行服务端的断言。例如,如果该标记在HTTP段中设置了一些对象,你就可以断言在那里。
4.Cactus JSP Redirector将标记的输出通过HTTP响应返回到客户端。然后在JspTestCase类编写一个endXXX方法来断言标记的输出。Cactus提供了同HttpUnit的紧密集成,它将允许你对返回的标记内容定义精确的断言。
定义自定义标记
在结果视图中,我们使用的第一个标记类将是DynaPropertiesTag。这个标记从DynaBean对象中取出所用的属性放到一个数组里。这些属性都是DynaProperty的对象,存放在PageContext中的一个连接到标记的目录下。下面是该标记的用法:
<d:properties var="<span style=" color:="" #8b0000"="">properties" item="${dynaBean}"/>
其中properties表示DynaProperty对象数组的变量名,dynaBean是用来获取属性信息的DynaBean实例。
DynaProoertiesTag如下:
package junitbook.pages; import org.apache.commons.beanutils.DynaBean; import org.apache.taglibs.standard.lang.support.ExpressionEvaluatorManager; import javax.servlet.jsp.tagext.TagSupport; import javax.servlet.jsp.JspException; public class DynaPropertiesTag extends TagSupport { private String varName; private String item; public void setVar(String varName) { this.varName = varName; } public String getVar() { return this.varName; } public void setItem(String item) { this.item = item; } public String getItem() { return this.item; } public int doStartTag() throws JspException { // Evaluate the item attribute (an EL expression) which // must result in a DynaBean object. DynaBean bean = (DynaBean) ExpressionEvaluatorManager.evaluate( "item", getItem(), DynaBean.class, this, this.pageContext); // Get the DynaBean meta-properties and store them in the // variable pointed to by the "var" attribute. this.pageContext.setAttribute(getVar(), bean.getDynaClass().getDynaProperties()); return SKIP_BODY; } public int doEndTag() throws JspException { return EVAL_PAGE; } }
为了同JSTL库兼容,你可以用EL语言来实现item属性的内容。
测试自定义标记
下一个问题就是对自定义标记进行单元测试
你需要证实这个标记是否正确的存储了DynaBean对象在PageContext范围内传递属性。
package junitbook.pages; import org.apache.cactus.JspTestCase; import org.apache.commons.beanutils.DynaProperty; import org.apache.commons.beanutils.BasicDynaClass; import org.apache.commons.beanutils.DynaBean; import javax.servlet.jsp.tagext.Tag; public class TestDynaPropertiesTag extends JspTestCase { private DynaBean createDynaBean() throws Exception { DynaProperty[] props = new DynaProperty[] { new DynaProperty("id", String.class), new DynaProperty("responsetime", Long.class) }; BasicDynaClass dynaClass = new BasicDynaClass("requesttime", null, props); DynaBean bean = dynaClass.newInstance(); bean.set("id", "12345"); bean.set("responsetime", new Long(500)); return bean; } public void testDoStartTag() throws Exception { DynaPropertiesTag tag = new DynaPropertiesTag();创建用于测试的标记实例 tag.setPageContext(pageContext); pageContext.setAttribute("item", createDynaBean()); 设置页面上下文初始化标记 tag.setItem("${item}"); 为标记设置环境参数 tag.setVar("var"); int result = tag.doStartTag(); assertEquals(Tag.SKIP_BODY, result); 执行后断言服务端的环境 assertTrue(pageContext.getAttribute("var") instanceof DynaProperty[]); DynaProperty[] props = (DynaProperty[]) pageContext.getAttribute("var"); assertEquals(props.length, 2); } }
该标记实现比较简单,并且实现了一个当生命周期的doStart方法。一个简单标记的生命周期为:
ATag t =new ATag();
t.setPageContext(…);
t.setParent(…);
t.setProperty1(value1);
[…]
t.setPropertyN(ValueN);
t.doStartTag();
t.doEndTag();
t.release();
在本例中你需要初始化该标记。