Docs for: v1.7.2 | v1.7 Last update: March 26 2006

# When to use? Your test case class should extend `JspTestCase` whenever you are unit testing: Custom tags, Any java code that uses JSP API objects (`PageContext`, ...) This tutorial focuses on testing custom tags, as they are the principal code which uses the JSP API objects. Future versions of this tutorial will expand upon testing actual JSPs. # Overview of Tag Library Testing Custom tags consist of entries in a Tag Library Descriptor file (TLD) and a tag handler class. Cactus provides the facility to test both aspects of a custom tag. However, since the TLD contains no logic, you will use Cactus primarily to test the tag handler class. To test the tag handler class, use the implicit objects provided by JspTestCase to set up the initial state for the test. Then create and initialize your custom tag using the `pageContext` implicit object. After setting up the tag, call the lifecycle methods implemented by your tag in the correct order and verify that the methods return the expected results. The tag's output can be inspected in the `endXXX()` method. For an additional degree of integration testing, you can create a JSP that exercises your custom tag and call it from within a regular Cactus test case. See the section on Further Integration Testing for details. To simplify the complexities of managing a tag handlers lifecycle, Cactus provides the helper class `JspTagLifecycle`. It is basically a stub implementation of a JSP engines tag management routines, and provides many convenient shortcut methods to test tag handlers. For detailled documentation, check out the corresponding API documentation. Currently, `JspTagLifecycle` is only available for JSP 1.2. # Provided Implicit Objects Cactus automatically initializes the following implicit objects. They are made available to your `setUp()`, `testXXX()` and `tearDown()` methods as instance variables of the `JspTestCase` class (and thus as instance variables of your test case class). See the How it works guide for details on how Cactus initializes these objects. The provided implicit objects are: ## request See `ServletTestCase` `request` implicit object for documentation. ## response See `ServletTestCase` `response` implicit object for documentation. ## config See `ServletTestCase` `config` implicit object for documentation. ## session See `ServletTestCase` `session` implicit object for documentation. ## out
Instance variable name | `out`
Class name | `public javax.servlet.jsp.JspWriter`
Cactus does not wrap the out object. You can use this object to write data to the response, thereby simulating the body of a tag (if the tag does not modify its body). If the tag does modify its body, then you will need to generate a BodyContent object before writing out the simualted body. See `bodyContent` for details. ## pageContext
Instance variable name | `pageContext`
Class name | `org.apache.cactus.server.PageContextWrapper` , which inherits from `javax.servlet.jsp.PageContext`
Custom tags rely exclusively on the `pageContext` object to provide information about the enclosing JSP. Therefore this is the most important implicit object for testing custom tags. Cactus provides a very thin wrapper that ensures that all of the objects that `pageContext` returns (such as the `ServletRequest` from `pageContext.getRequest()`) are the correctly wrapped versions available in the other implicit variables. See the javadoc for `org.apache.cactus.server.PageContextWrapper` for more details. You should also look at the samples provided in the Cactus distribution. ## bodyContent
Instance variable name | `bodyContent`
Class name | `javax.servlet.jsp.tagext.BodyContent`
JspTestCase does not actually provide a `bodyContent` implicit object for use with `BodyTags`. However, obtaining one is so easy that it deserves mention here. Calling `pageContext.pushBody()` returns an object of type `javax.servlet.jsp.tagext.BodyContent` (which inherits from `JspWriter`). This call also changes the value of the "out" variable stored in page scope (and thus the value of `pageContext.getOut()`). To put test content into the `bodyContent` object, simply use its writer methods. To quote Sun's API reference on the matter: "Note that the content of BodyContent is the result of evaluation, so it will not contain actions and the like, but the result of their invocation." See Body Tags for more information. It's important to balance calls to `pushBody()` with calls to `popBody()`--otherwise many servlet engines will not output the tag's body. The easiest way to accomplish this is to call pushBody in `setUp()` and `popBody()` in `tearDown()`. # Custom Tag Set Up Creating the test fixture for a custom tag test involves several steps. The exact order of the steps can vary depending on the needs of the test. For instance, placing the test data in the correct scope would probably happen before a real JSP began its execution. You can emulate this, or choose to do it after the tag has been in initialized (as described below). In most cases you can determine the exact order of the steps based on what is most convenient for a given test (some steps may be specific to only one test in the `TestCase` and so should be executed after common `setUp()` code). ## Step 1: Create the Tag (Required) Instantiate a copy of the tag you wish to test.
    SomeTag tag = new SomeTag();
## Step 2: Set the pageContext (Optional) Call the `setPageContext()` method with the implicit object provided by Cactus to register the pageContext with the tag.
    tag.setPageContext(pageContext);
## Step 3: Set the tag's attributes (Optional) If your tag takes attributes, call setter methods to initialize the tag's state. Setters on the tag handler class represent the attributes of custom tags. Thus to emulate this JSP fragment:
    <someTag foo="10" bar="11"/>
You would need to use the following:
    someTag.setFoo("10");
    someTag.setBar("11");
## Step 4: Set the parent tag (Optional) If you would like the tag you are testing to access a parent tag, you will need to call
    tag.setParent(enclosingTag);
This will allow tag to successfully call `getParent` and `TagSupport.findAncestorWithClass()`. Of course `enclosingTag` will have to be instantiated and set up as well, including another call to `setParent()` if you would like to simulate multiple levels of nesting. ## Step 5: Create the BodyContent Object (Optional) If your tag processes its body, call `pageContext.pushBody()` to obtain a `BodyContent`. If you employ this step, be sure to also include a call to `pageContext.popBody()` after the tag finishes execution. See the Body Tags section for more details. ## Step 6: Set up page state (Optional) Set up any necessary page state by putting test objects into the appropriate scopes. Tags frequently access data in the session, the request, or the page. If your tag operates on data contained in any of these (or in the application scope), be sure to set up this part of the test fixture. Objects can be placed in these scopes by using the implicit objects provided by Cactus directly, or by accessing them indirectly through the `pageContext` object.
    request.setAttribute("key", new DomainObject("testValue"));
    //or
    pageContext.setAttribute("key", new DomainObject("testValue"), PageContext.REQUEST_SCOPE);
# Running the Test Once the tag has been set up and any necessary page data has been placed in the appropriate scopes, testing a custom tag consists of calling the relevant life-cycle methods and then using JUnit asserts to verify the outcome. ## Verifying individual methods Most of the life cycle methods return `ints`, which signal that the container should take a certain action after the method. For instance, the constant `EVAL_BODY_INCLUDE` returned from `doStartTag()` tells the container to include the tag's body in the JSP's output response. So a tag which conditionally includes its body based on the value of one of its attributes might be verified like this:
    tag.setValueThatResultsInInclude("correct value");
    assertEquals(Tag.EVAL_BODY_INCLUDE, tag.doStartTag());
## Checking effects on page data In addition to "listening" for the signals that your tag sends to the container, you may want to verify that the tag's execution has the appropriate effects upon the page data. Use `JspTestCase's` implicit objects to verify that the tag has correctly modified the information. The following snippet verifies that the `CatalogListTag` has placed a collection of objects in the request under the key "catalogs":
    catalogListTag.doStartTag();
    Collection catalogs = (Collection)request.getAttribute("catalogs");
    assertNotNull(catalogs);
## Verifying tag output Use the `endXXX` method to verify that your tag's methods have resulted in the correct data being written to the response. This example uses the `endXXX()` signature from Cactus 1.2 or above.
    public void endSomeTagTest (WebResponse response)
    {
        String output = response.getText();
        assertEquals("<b>expected output</b>", output);
    }
# Special Cases There are a few scenarios in custom tag testing that deserve extra attention. ## Iteration Tags To test a tag that repeats its body processing a number of times, simply create a `do-while` loop that mimics the life cycle of an iteration tag:
    //[...tag set up and early life cycle methods omitted...]

    int count = 0;
    do
    {
        count++;

    } while (tag.doAfterBody() == tag.EVAL_BODY_AGAIN);

    tag.doEndTag();

    //based on setUp we expect 9 repetitions
    assertEquals(9, count);
You can use a count variable (such as the one illustrated in the example) to check whether the tag's body was processed the expected number of times. ## Body Tags Unless specified otherwise by the deployment descriptor, all tags can include a body, which can in turn include other tags or scriptlet expressions. These are automatically evaluated at run time, and the content of the body is simply written out if the tag signals it should be (with `EVAL_BODY_INCLUDE` for instance). Nothing special is required to test this sort of tag, since the tag is unconcerned about its contents. Testing BodyTags--tags which actually perform some processing on their content--is a little trickier. BodyTags can choose to return a constant ( `EVAL_BODY_TAG` in JSP 1.1, `EVAL_BODY_BUFFERED` in 1.2) from `doStartTag()` which signals to the container that the tag would like a chance to handle its own body. If it receives this result, the container calls `pageContext.pushBody()` to obtain a `BodyContent`object. The `BodyContent` object is passed to the tag through the tag's `setBodyContent()`method. The container then uses this object (the old out object is saved) to capture all of the response writing that goes on in the body of the tag. After the tag's body has been evaluated, the tag itself has a chance to do something with the result of the evaluation in its `doAfterBody()` method. After the tag has completed its execution, the container restores the old out object with a call to `pageContext.popBody()`. To test body tags, your test must replicate this somewhat complicated lifecycle. The following code covers all of the steps as they might appear in a typical test:
    //standard set up
    YourTag tag = new YourTag();
    tag.setPageContext(this.pageContext);
    tag.doStartTag();

    //obtain the bodyContent object--presumably doStartTag has returned
    //EVAL_BODY_TAG or EVAL_BODY_BUFFERED.
    BodyContent bodyContent = this.pageContext.pushBody();
    this.tag.setBodyContent(bodyContent);
    this.tag.doInitBody();

    //write some "output" into the bodyContent so that endXXX can test for it.
    bodyContent.println("Some content");
    bodyContent.print("Some evaluated content " + (5 + 9));

    //actually handles the processing of the body
    tag.doAfterBody();

    //after the body processing completes
    tag.doEndTag();

    //finally call popBody
    this.pageContext.popBody();
This sample does not fully replicate the container's handling of the tag (for instance, the tag would only receive the `bodyContent` object if the result of `doStartTag` indicated that it should do so). However, in a test environment, you can make assumptions if doing so simplifies the workings of the test. Again, you can check that the body of the tag was handled correctly by verifying the total output in the `endXXX()` method. ## TagExtraInfo classes Cactus does not offer any specific services to support the testing of `TagExtraInfo` classes because they do not depend on any of the implicit objects. # Further Integration Testing You can use Cactus to test how your tag will react when put into a real JSP. This allows you to verify that there are no problems with the deployment descriptor, or unexpected behavior on the part of the container. You accomplish this by writing a small JSP that makes use of your custom tag, and then calling it from within a Cactus test case. You can even use JUnit assertions within scriptlets to verify certain aspects of the Tag's behavior. However, this method requires that you write a separate JSP for each test case (or lump several cases into a single JSP). Both options pose problems, so it may be best to include one or two tests of this type and rely on the more traditional methods described earlier to ensure total coverage. ## The test JSP All the JSP needs to do is include the tag library that describes the tag you are testing and makes use of it in some way. You can import `junit.framework.Assert` to do some simple checks on the effects of the tag. Here is a short example of a JSP that exercises a tag:
    <%@page import="junit.framework.Assert"%>
    <%@taglib uri="WEB-INF/yourTagLib.tld" prefix="example"%>

    Here is the custom tag this page verifies:
    <example:someTag variableName="foo" variableValue="bar"/>

    Here is the JUnit assert that checks whether the tag correctly created a
    scripting variable named <code>foo</code> with the value "bar":
    <%
    //attempt to reference foo will cause a translation error if the tag did not
    //create the scripting variable
    Assert.assertEquals("bar", foo);
    %>
It's a bad idea to put too many assertions into the JSP. In the example above, the creation of a scripting variable can only be tested within the JSP page. (The same goes for any objects in page scope, because each JSP creates its own.) If you want to use other assertions with this type of test, call them in your test case after `pageContext.include()` (See below for an example.) ## The TestCase To use the test JSP, include it from within a `JspTestCase.` The convenience function `pageContext.include()` takes care of this nicely:
    public void testSomeTag () throws Exception
    {
        pageContext.include("/test_some_tag.jsp");

        //an assert to check whether the page also mapped foo into the session
        assert("bar", session.getAttribute("foo"));
    }
Exceptions that result from either page translation (such as required attributes being omitted, or the tag missing a part of its descriptor entry) or page execution (such as the tag being unable to find required data in the appropriate scope) are automatically be thrown up to this level. If you do not catch them there they will be logged by Cactus/JUnit as failures--which is just what you want. Any output that the test JSP generates can be checked normally in the `endXXX` method. Of course, using this strategy means that you need to put the `test_some_tag.jsp` in the specified location within your web application. If you are using JSP test case your build script should already deploy the redirector JSP, so it should be easy to include another JSP in the build process.