vmassol 2002/11/26 01:22:47
Modified: framework/src/java/j2ee13/org/apache/cactus/extension/jsp
JspTagLifecycle.java
sample-servlet/src/unit/j2ee13/org/apache/cactus/unit
TestJspTagLifecycle.java
Added: framework/src/java/j2ee13/org/apache/cactus/extension/jsp
package.html
Log:
Patch from Chris Lenz for JspTagLifeCycle: fixed coding style, added lots of javadoc
comments, some bug fixes.
Revision Changes Path
1.2 +122 -18
jakarta-cactus/framework/src/java/j2ee13/org/apache/cactus/extension/jsp/JspTagLifecycle.java
Index: JspTagLifecycle.java
===================================================================
RCS file:
/home/cvs/jakarta-cactus/framework/src/java/j2ee13/org/apache/cactus/extension/jsp/JspTagLifecycle.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- JspTagLifecycle.java 24 Nov 2002 21:44:56 -0000 1.1
+++ JspTagLifecycle.java 26 Nov 2002 09:22:47 -0000 1.2
@@ -70,6 +70,109 @@
* Convenience class that supports the testing of JSP tag by managing the tag's
* lifecycle as required by the JSP specification.
*
+ * <p>
+ * This class is basically a stub implementation of the tag management
+ * facilities that an actual JSP container would provide. The implementation
+ * attempts to follow the specification as closely as possible, but the tag
+ * handling functionality of real JSP implementations may vary in some
+ * details.
+ * </p>
+ *
+ * <p>
+ * Although this class works quite well when used in the test methods of a
+ * {@link org.apache.cactus.JspTestCase JspTestCase}, it can also safely be
+ * used outside of the Cactus testing framework, for example when following
+ * a mock objects approach.
+ * </p>
+ *
+ * <h4>Testing Simple Tags</h4>
+ * <p>
+ * This is how you would use this class when testing the
+ * <code><c:set></code>-tag of the JSTL reference implementation:
+ * <blockquote><pre>
+ SetTag tag = new SetTag();
+ JspTagLifecycle lifecycle = new JspTagLifecycle(pageContext, tag);
+ tag.setVar("name");
+ tag.setValue("value");
+ lifecycle.invoke();
+ assertEquals("value", pageContext.findAttribute("name"));</pre>
+ * </blockquote>
+ * The order is important:
+ * <ol>
+ * <li>
+ * Instantiation of the tag under test
+ * </li>
+ * <li>
+ * Instantiation of the lifecycle helper, passing in the page context,
+ * the tag instance and optionally the parent tag
+ * </li>
+ * <li>
+ * Set the tag's attributes
+ * </li>
+ * <li>
+ * Start the tag's lifecycle by calling
+ * {@link #invoke() JspTagLifecycle.invoke()}
+ * </li>
+ * <li>
+ * Make assertions
+ * </li>
+ * </ol>
+ * </p>
+ *
+ * <h4>Testing Iteration and Body Tags with Lifecycle Interceptors</h4>
+ * <p>
+ * In the example above, the tag's lifecycle is simply run through from start
+ * to finish. However, <code>JspTagLifecycle</code> also let's you get
+ * <em>inside</em> significant phases of the tag's lifecycle. For this you
+ * need to use the method
+ * {@link #invoke(JspTagLifecycle.Interceptor) invoke(Interceptor)}
+ * supplying a custom
+ * {@link JspTagLifecycle.Interceptor Interceptor} implementation.
+ * </p>
+ *
+ * <p>
+ * This feature can be used to test iteration and body tags. The following
+ * code snippet is a simple example for testing the
+ * <code><c:forEach></code>-tag of the JSTL reference implementation:
+ * <blockquote><pre>
+ ForEachTag tag = new ForEachTag();
+ JspTagLifecycle lifecycle = new JspTagLifecycle(pageContext, tag);
+ tag.setVar("item");
+ tag.setItems("one,two,three");
+ lifecycle.invoke(new JspTagLifecycle.Interceptor() {
+ public void evalBody(int iteration, BodyContent body) {
+ String item = (String)pageContext.findAttribute("item");
+ if (iteration == 0) {
+ assertEquals("one", item);
+ } else if (iteration == 1) {
+ assertEquals("two", item);
+ } else if (iteration == 2) {
+ assertEquals("three", item);
+ } else {
+ fail("More iterations than expected!");
+ }
+ }
+ });</pre>
+ * </blockquote></p>
+ *
+ * <p>
+ * To test a tag that does buffered evaluation of its body content, the
+ * {@link JspTagLifecycle.Interceptor#evalBody Interceptor.evalBody()} method
+ * can be overridden to write the content that the tag will see. The following
+ * example demonstrates this using the <code><c:out></code> tag:
+ * <blockquote><pre>
+ OutTag tag = new OutTag();
+ JspTagLifecycle lifecycle = new JspTagLifecycle(pageContext, tag);
+ tag.setValue(null);
+ lifecycle.invoke(new JspTagLifecycle.Interceptor() {
+ public void evalBody(int iteration, BodyContent body)
+ throws IOException {
+ body.print("Default Value");
+ }
+ });
+ </blockquote>
+ * </p>
+ *
* @author <a href="mailto:[EMAIL PROTECTED]">Christopher Lenz</a>
*
* @version $Id$
@@ -80,7 +183,10 @@
// Inner Classes -----------------------------------------------------------
/**
- *
+ * Abstract class for intercepting the tag lifecycle. You can override any
+ * of the methods to insert assertions that verify the tag's behaviour while
+ * it is being executed.
+ *
* @author <a href="mailto:[EMAIL PROTECTED]">Christopher Lenz</a>
*/
public abstract static class Interceptor
@@ -161,17 +267,19 @@
public JspTagLifecycle(PageContext thePageContext, Tag theTag,
Tag theParent)
{
- this.pageContext = thePageContext;
this.tag = theTag;
+ this.pageContext = thePageContext;
+ tag.setPageContext(pageContext);
this.parent = theParent;
+ tag.setParent(parent);
}
// Public Methods ----------------------------------------------------------
/**
- * Invokes the tag in the provided page context. The tag should have been
- * populated with its properties before calling this method. The tag is not
- * released after the tag's lifecycle is over.
+ * Invokes the tag. The tag should have been populated with its properties
+ * before calling this method. The tag is not released after the tag's
+ * lifecycle is over.
*
* @throws JspException If the tag throws an exception
* @throws IOException If an error occurs when reading or writing the body
@@ -183,12 +291,12 @@
}
/**
- * Invokes the tag in the provided page context. The tag should have been
+ * Invokes the tag with the provided interceptor. The tag should have been
* populated with its properties before calling this method. The tag is not
* released after the tag's lifecycle is over.
*
* @param theInterceptor The interceptor that will be notified about
- * lifecycle events
+ * important lifecycle events
* @throws JspException If the tag throws an exception
* @throws IOException If an error occurs when reading or writing the body
* content
@@ -200,11 +308,7 @@
{
throw new NullPointerException();
}
-
- tag.setPageContext(pageContext);
- tag.setParent(parent);
BodyContent body = null;
-
if (tag instanceof TryCatchFinally)
{
TryCatchFinally tryCatchFinally = (TryCatchFinally) tag;
@@ -268,9 +372,9 @@
{
BodyContent body = null;
int status = tag.doStartTag();
- if (status != Tag.SKIP_BODY)
+ if (tag instanceof IterationTag)
{
- if (tag instanceof IterationTag)
+ if (status != Tag.SKIP_BODY)
{
IterationTag iterationTag = (IterationTag) tag;
if ((status == BodyTag.EVAL_BODY_BUFFERED)
@@ -289,10 +393,10 @@
iteration++;
} while (status == IterationTag.EVAL_BODY_AGAIN);
}
- }
- else
- {
- theInterceptor.skipBody();
+ else
+ {
+ theInterceptor.skipBody();
+ }
}
status = tag.doEndTag();
return body;
1.1
jakarta-cactus/framework/src/java/j2ee13/org/apache/cactus/extension/jsp/package.html
Index: package.html
===================================================================
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
<html>
<head>
<title></title>
</head>
<body>
<p>
Contains utility classes to support unit testing of JSP tag libraries.
</p>
</body>
</html>
1.2 +164 -97
jakarta-cactus/sample-servlet/src/unit/j2ee13/org/apache/cactus/unit/TestJspTagLifecycle.java
Index: TestJspTagLifecycle.java
===================================================================
RCS file:
/home/cvs/jakarta-cactus/sample-servlet/src/unit/j2ee13/org/apache/cactus/unit/TestJspTagLifecycle.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- TestJspTagLifecycle.java 24 Nov 2002 21:44:55 -0000 1.1
+++ TestJspTagLifecycle.java 26 Nov 2002 09:22:47 -0000 1.2
@@ -71,21 +71,29 @@
import org.apache.taglibs.standard.tag.el.core.WhenTag;
/**
+ * Tests for the <code>JspTagLifecycle</code> extension.
*
+ * <p>
+ * The lifecycle helper is tested here by testing the reference implementation
+ * of the JSP standard tag library (JSTL), available at
+ * <a href="http://jakarta.apache.org/taglibs/">.
+ * </p>
*
* @author <a href="mailto:[EMAIL PROTECTED]">Christopher Lenz</a>
*/
public class TestJspTagLifecycle
- extends JspTestCase {
+ extends JspTestCase
+{
// Constructors ------------------------------------------------------------
/**
- * Defines the testcase name for JUnit.
- *
- * @param theName the testcase's name.
+ * Constructor.
+ *
+ * @param theName The name of the test case
*/
- public TestJspTagLifecycle(String theName) {
+ public TestJspTagLifecycle(String theName)
+ {
super(theName);
}
@@ -104,123 +112,153 @@
// Test Methods ------------------------------------------------------------
/**
+ * Tests the <code><c:out></code>-tag with a proper, literal value for
+ * it's <code>value</code> attribute.
*
- * @throws JspException
- * @throws IOException
+ * @throws JspException If the tag throws a JSPException
+ * @throws IOException If the tag throws an IOException
*/
public void testOutTag()
- throws JspException, IOException {
-
+ throws JspException, IOException
+ {
OutTag tag = new OutTag();
- tag.setValue("TEST");
JspTagLifecycle lifecycle = new JspTagLifecycle(pageContext, tag);
- lifecycle.invoke(new JspTagLifecycle.Interceptor() {
- public void evalBody(int iteration, BodyContent body) {
- assertEquals("TEST", body.getString());
- }
- });
+ tag.setValue("Value");
+ lifecycle.invoke();
}
/**
+ * Verifies that the response has been correctly rendered by the
+ * <code><c:out></code>-tag.
*
- * @param theResponse
+ * @param theResponse The HTTP response
*/
- public void endOutTag(WebResponse theResponse) {
-
+ public void endOutTag(WebResponse theResponse)
+ {
String output = theResponse.getText();
- assertEquals("TEST", output);
+ assertEquals("Value", output);
}
/**
+ * Tests the <code><c:out></code>-tag with <code>null</code> for
+ * it's <code>value</code> attribute, and a proper, literal value for it's
+ * <code>default</code> attribute.
*
- * @throws JspException
- * @throws IOException
+ * @throws JspException If the tag throws a JSPException
+ * @throws IOException If the tag throws an IOException
*/
public void testOutTagDefaultAttribute()
- throws JspException, IOException {
-
+ throws JspException, IOException
+ {
OutTag tag = new OutTag();
- tag.setValue(null);
- tag.setDefault("Default Value");
JspTagLifecycle lifecycle = new JspTagLifecycle(pageContext, tag);
+ tag.setValue(null);
+ tag.setDefault("Default");
lifecycle.invoke();
}
/**
- *
- * @param theResponse
+ * Verifies that the response has been correctly rendered by the
+ * <code><c:out></code>-tag.
+ *
+ * @param theResponse The HTTP response
*/
- public void endOutTagWithDefaultAttribute(WebResponse theResponse) {
-
+ public void endOutTagWithDefaultAttribute(WebResponse theResponse)
+ {
String output = theResponse.getText();
- assertEquals("Default Value", output);
+ assertEquals("Default", output);
}
/**
+ * Tests the <c:out>-Tag with a value that evaluates to
+ * <code>null</code>, and the default value specified in the tag's body.
*
- * @throws JspException
- * @throws IOException
+ * @throws JspException If the tag throws a JSPException
+ * @throws IOException If the tag throws an IOException
*/
public void testOutTagDefaultBody()
- throws JspException, IOException {
-/*
+ throws JspException, IOException
+ {
OutTag tag = new OutTag();
+ JspTagLifecycle lifecycle = new JspTagLifecycle(pageContext, tag);
tag.setValue(null);
- new JspTagLifecycle(tag) {
- protected void evalBody(int iteration, BodyContent body)
- throws IOException {
- body.print("Default Value");
+ lifecycle.invoke(new JspTagLifecycle.Interceptor()
+ {
+ public void evalBody(int iteration, BodyContent body)
+ throws IOException
+ {
+ body.print("Default");
}
- }.invoke(pageContext, null);*/
+ });
}
/**
+ * Verifies that the response has been correctly rendered by the
+ * <code><c:out></code>-tag.
*
- * @param theResponse
+ * @param theResponse The HTTP response
+ * @todo This test currently fails if commented in
*/
- public void endOutTagDefaultBody(WebResponse theResponse) {
-/*
+ public void endOutTagDefaultBody(WebResponse theResponse)
+ {
String output = theResponse.getText();
- assertEquals("Default Value", output);*/
+ //assertEquals("Default", output);
}
/**
+ * Tests the <c:set>-tag with a proper, literal values for it's
+ * <code>var</code> and <code>value</code> attributes. Verification is done
+ * by checking the scoped variable stored by the tag.
*
- * @throws JspException
- * @throws IOException
+ * @throws JspException If the tag throws a JSPException
+ * @throws IOException If the tag throws an IOException
*/
public void testSetTag()
- throws JspException, IOException {
-
+ throws JspException, IOException
+ {
SetTag tag = new SetTag();
- tag.setVar("name");
- tag.setValue("value");
JspTagLifecycle lifecycle = new JspTagLifecycle(pageContext, tag);
+ tag.setVar("Var");
+ tag.setValue("Value");
lifecycle.invoke();
- assertEquals("value", pageContext.findAttribute("name"));
+ assertEquals("Value", pageContext.findAttribute("Var"));
}
/**
+ * Tests the tag <c:forEach> by providing a comma-delimited list of
+ * string to it's <code>items</code> attributes, and checking the exposed
+ * scoped variable on every iteration step.
*
- * @throws JspException
- * @throws IOException
+ * @throws JspException If the tag throws a JSPException
+ * @throws IOException If the tag throws an IOException
*/
public void testForEachTag()
- throws JspException, IOException {
-
+ throws JspException, IOException
+ {
ForEachTag tag = new ForEachTag();
- tag.setVar("item");
- tag.setItems("uno,dos,tres");
JspTagLifecycle lifecycle = new JspTagLifecycle(pageContext, tag);
- lifecycle.invoke(new JspTagLifecycle.Interceptor() {
- public void evalBody(int iteration, BodyContent body) {
- if (iteration == 0) {
- assertEquals("uno", pageContext.findAttribute("item"));
- } else if (iteration == 1) {
- assertEquals("dos", pageContext.findAttribute("item"));
- } else if (iteration == 2) {
- assertEquals("tres", pageContext.findAttribute("item"));
- } else {
+ tag.setVar("Item");
+ tag.setItems("One,Two,Three");
+ lifecycle.invoke(new JspTagLifecycle.Interceptor()
+ {
+ public void evalBody(int iteration, BodyContent body)
+ {
+ String item = (String)pageContext.findAttribute("Item");
+ assertNotNull(item);
+ if (iteration == 0)
+ {
+ assertEquals("One", item);
+ }
+ else if (iteration == 1)
+ {
+ assertEquals("Two", item);
+ }
+ else if (iteration == 2)
+ {
+ assertEquals("Three", item);
+ }
+ else
+ {
fail("More iterations than expected!");
}
}
@@ -228,95 +266,124 @@
}
/**
+ * Tests the conditional tag <c:if> by providing a proper, literal
+ * value to it's <code>test</code> attribute that evaluates to
+ * the boolean value <code>true</code>. The test verifies the correct
+ * behaviour by asserting that the tag's body is not skipped.
*
- * @throws JspException
- * @throws IOException
+ * @throws JspException If the tag throws a JSPException
+ * @throws IOException If the tag throws an IOException
*/
public void testIfTagTrue()
- throws JspException, IOException {
-
+ throws JspException, IOException
+ {
IfTag tag = new IfTag();
- tag.setTest("true");
JspTagLifecycle lifecycle = new JspTagLifecycle(pageContext, tag);
- lifecycle.invoke(new JspTagLifecycle.Interceptor() {
- public void skipBody() {
+ tag.setTest("true");
+ lifecycle.invoke(new JspTagLifecycle.Interceptor()
+ {
+ public void skipBody()
+ {
fail("Body should have been evaluated!");
}
});
}
/**
+ * Tests the conditional tag <c:if> by providing a proper, literal
+ * value to it's <code>test</code> attribute that evaluates to
+ * the boolean value <code>false</code>. The test verifies the correct
+ * behaviour by asserting that the tag's body is not evaluated.
*
- * @throws JspException
- * @throws IOException
+ * @throws JspException If the tag throws a JSPException
+ * @throws IOException If the tag throws an IOException
*/
public void testIfTagFalse()
- throws JspException, IOException {
-
+ throws JspException, IOException
+ {
IfTag tag = new IfTag();
- tag.setTest("false");
JspTagLifecycle lifecycle = new JspTagLifecycle(pageContext, tag);
- lifecycle.invoke(new JspTagLifecycle.Interceptor() {
- public void evalBody(int iteration, BodyContent body) {
+ tag.setTest("false");
+ lifecycle.invoke(new JspTagLifecycle.Interceptor()
+ {
+ public void evalBody(int iteration, BodyContent body)
+ {
fail("Body should have been skipped!");
}
});
}
/**
+ * Tests the <c:when>-tag correctly nested inside a <c:choose>
+ * tag, and providing a proper, literal value to it's <code>test</code>
+ * attribute that evaluates to the boolean value <code>true</code>. The test
+ * verifies the correct behaviour by asserting that the tag's body is not
+ * skipped.
*
- * @throws JspException
- * @throws IOException
+ * @throws JspException If the tag throws a JSPException
+ * @throws IOException If the tag throws an IOException
*/
public void testWhenTag()
throws JspException, IOException
{
-
WhenTag tag = new WhenTag();
- tag.setTest("true");
JspTagLifecycle lifecycle =
new JspTagLifecycle(pageContext, tag, new ChooseTag());
- lifecycle.invoke(new JspTagLifecycle.Interceptor() {
- public void skipBody() {
+ tag.setTest("true");
+ lifecycle.invoke(new JspTagLifecycle.Interceptor()
+ {
+ public void skipBody()
+ {
fail("Body should have been evaluated!");
}
});
}
/**
+ * Tests the <c:when>-tag correctly nested inside a <c:choose>
+ * tag, and providing a proper, literal value to it's <code>test</code>
+ * attribute that evaluates to the boolean value <code>true</code>. However,
+ * an earlier instance of the <code><c:when></code> tag nested in the
+ * parent has already succeeded, so this test asserts that the body of the
+ * later <code><c:when></code> does not get evaluated.
*
- * @throws JspException
- * @throws IOException
+ * @throws JspException If the tag throws a JSPException
+ * @throws IOException If the tag throws an IOException
*/
public void testWhenTagNoPermission()
throws JspException, IOException
{
-
ChooseTag parent = new ChooseTag();
parent.subtagSucceeded();
WhenTag tag = new WhenTag();
- tag.setTest("true");
JspTagLifecycle lifecycle =
new JspTagLifecycle(pageContext, tag, parent);
- lifecycle.invoke(new JspTagLifecycle.Interceptor() {
- public void evalBody(int iteration, BodyContent body) {
+ tag.setTest("true");
+ lifecycle.invoke(new JspTagLifecycle.Interceptor()
+ {
+ public void evalBody(int iteration, BodyContent body)
+ {
fail("Body should have been skipped!");
}
});
}
/**
+ * Tests te <code><c:when></code> tag not nested inside a
+ * <code><c:choose></code> tag. The test expects a
+ * <code>JspException</code> to be thrown.
*
- * @throws JspException
- * @throws IOException
+ * @throws JspException If the tag throws a JSPException
+ * @throws IOException If the tag throws an IOException
*/
public void testWhenTagWithoutChooseTag()
- throws JspException, IOException {
-
+ throws JspException, IOException
+ {
WhenTag tag = new WhenTag();
+ JspTagLifecycle lifecycle = new JspTagLifecycle(pageContext, tag);
tag.setTest("true");
- try {
- JspTagLifecycle lifecycle = new JspTagLifecycle(pageContext, tag);
+ try
+ {
lifecycle.invoke();
fail("Expected JSPTagException");
} catch (JspTagException je) {
--
To unsubscribe, e-mail: <mailto:[EMAIL PROTECTED]>
For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>