Testing Body Tags

Tags that perform processing on their body use a BodyContent object to access their page content. BodyContent extends JspWriter and nests within another JspWriter, possibly another BodyContent object. You should keep these facts in mind; they indicate that the BodyContent object contains the result of the evaluation of the body, not the unaltered content of the body as it appears on the JSP page. Imagine that one tag nests within another like this:


In this situation, child is evaluated first and simply writes its output (if any) into the BodyContent object of parent. When parent begins execution, its BodyContent object only contains the String results of child's processing. Although the concept may elude immediate understanding, it simplifies the testing of BodyTags. To test a tag that processes its body, simply write some test data into a BodyContent object and pass it to the tag in question. See the section "Working with Nested Tags" for further information. To obtain a suitable BodyContent, use pageContext.pushBody(). This method returns a new BodyContent object nested within the previous JspWriter. This operation also updates the value of the JspWriter contained in the page scope (available with pageContext.getOut()) to the new BodyContent. Most translated servlets perform the operation like this:

out = pageContext.pushBody();
tag.setBodyContent((BodyContent) out);

(out is the standard JSP implicit variable.) Let's look at an example.

productLink Tag Example

The productLink tag turns its contents into a hyperlink that points to the product page on the current Web site. The product page requires an ID in the request, so the productLink tag accepts an "id" attribute. JSP designers use productLink tags like this:

<example:productLink product >
 Check out the Bastion of Fun (TM)

The tag handler class is simple. It writes out the opening <a> tag, then the content of the tag, and finally the closing </a>. The following listing displays the code.

public class ProductLinkTag extends BodyTagSupport{
 private String productId; public void setProductId(String id) {
 this.productId = id;
 public int doAfterBody()throws JspTagException{
 JspWriter writer = bodyContent.getEnclosingWriter();
 writer.print("<a href='product.jsp?id="+productId+"'>");
 catch( e){
 throw new JspTagException(e.toString()); }
 return BodyTag.EVAL_PAGE;

The test case builds upon the other test cases designed so far. A couple of extra steps are included to deal with the BodyContent object. Here is the setUp() method:

public void setUp() throws Exception{
 tag = new ProductLinkTag();
 out = pageContext.pushBody();
 /*not necessary since product link tag does not implement it,
 but this is where it would go in the standard lifecycle*/

Once the out variable is converted to an instance of BodyContent and registered with the tag, the test method can write sample content to it to be processed by the tag. In testDoAfterBody(), we print a manifest constant (for easy assertions later) as the body of the tag. Then we call doAfterBody() (which handles the body processing) and verify that it returns SKIP_BODY:

public void testDoAfterBody() throws Exception{
 /*violates strict life cycle order...but that should not have any effect on this tag, and results in better separation between setUp and
 test method*/
 int afterBodyResult = tag.doAfterBody();
 assertEquals(tag.SKIP_BODY, afterBodyResult);

endDoAfterBody()does most of the assertion work for us. First, we define the signature that uses HttpUnit's WebResponse, and then we use the convenience method getLinkWith(String) on WebResponse to search for the link with the text we specified earlier. If the search succeeds, we verify that the "href" attribute of the link indeed points to the product page:

/*using HttpUnit's WebResponse*/
public void endDoAfterBody(WebResponse resp)throws Exception{
 WebLink link = resp.getLinkWith(TEST_LINK_TEXT);
 String pointsTo = link.getURLString();
 assertEquals(TEST_LINK_TARGET, pointsTo);