JaVa
   

Testing Iteration Tags

The iteration tag life cycle specified by JSP 1.2 can be roughly represented with the following boilerplate code (ignoring extra stages that might occur because the tag might also be a BodyTag):

if(tag.doStartTag() != SKIP_BODY){
 do{
 /*body processing*/ }while(tag.doAfterBody() == EVAL_BODY_AGAIN);
}
/*evaluate doEndTag*/


To test an iteration tag, all we have to do is replicate this type of loop in a test method. If possible, we should also attempt to verify each life-cycle method in isolation. For instance, if the tag stops iterating after a certain variable in the page scope reaches a certain value, we could design a test method to verify that this was the case:

public void testAfterBodyConditions(){
 pageContext.setAttribute("shouldStop", new Boolean(true));
 assertEquals(tag.SKIP_BODY, tag.doAfterBody());
}


However, the boundary conditions of the loop may depend on an unexposed internal state. Although the tag under test can be modified to expose state, doing so may violate encapsulation. In these cases, the best option is to re-create the entire loop and verify that the tag body was processed the expected number of times.

Repeat Tag Example

We use this method to verify the behavior of a simple repeat tag. The tag takes a single attribute, "repetitions", which governs the number of times the tag body repeats without modification. This is how the repeat tag might appear in a JSP:

<%int count = 0;%>
<example:repeat repetitions="3">
 <%count++;%>
 Some content: <%=count%>
</example:repeat>


The following listing shows the code for the handler class.

public class RepeatTag extends javax.servlet.jsp.tagext.BodyTagSupport{
 private int repetitions;
 private int count;
 public void setRepetitions(String repetitions) {
 this.repetitions = Integer.parseInt(repetitions);
 }
 public void doInitBody(){
 /*doStartTag dicatates that the tag body will always be processed at
 *least once.
 */
 count = 1; }
 public int doStartTag(){
 if(repetitions > 0){
 return EVAL_BODY_INCLUDE;
 }
 return SKIP_BODY; }
 public int doAfterBody(){
 if(++count < repetitions){
 return EVAL_BODY_AGAIN;
 }
 return SKIP_BODY;
 }
}


Testing an iteration tag requires no special setup (beyond that required for any custom tag). First we verify that doStartTag() will go forward only if the number of repetitions has been set to a number greater than zero:

public void testDoStartTag() {
 tag.setRepetitions("0");
 int result = tag.doStartTag();
 assertEquals(tag.SKIP_BODY, result);
 tag.setRepetitions("2");
 result = tag.doStartTag();
 assertEquals(tag.EVAL_BODY_INCLUDE, result);
}


The second test method will validate the tag's behavior in the standard iteration loop:

public void testDoAfterBody() throws Exception {
 tag.setRepetitions("3");
 int count = 0;
 do{
 count++;
 out.print("Some content: " + count);
 }while(tag.doAfterBody() == tag.EVAL_BODY_AGAIN);
 assertEquals(3, count);
}


Before anything else, testDoAfterBody() sets the tag's repetitions attribute to a reasonable value. Then the method declares a local count variable to keep track of the number of loop executions. After running the do-while loop (terminated by the return value of doAfterBody()), the method verifies that the loop body has executed the expected number of times. The out.print(…) statement was inserted for illustration; because the tag includes the body without performing any tag-specific processing, it does not matter what goes on within the loop—only that it exists.


JaVa
   
Comments