In this recipe, we will discuss the JSFUnit, which is a JBoss framework for testing JSF applications. JSFUnit is based on the well known JUnit framework, but is more dedicated to JSF, because it runs in the container and it was created for understanding the main JSF concepts, such as JSF lifecycle, JSF components, Faces Context, EL expressions, and so on.
To describe it in detail, JSFUnit can be used for the following tests (as you can conclude from the following list, JSUnit can test JSF-specific tasks and more):
We developed this recipe with NetBeans 6.8, JSF 2.0, and GlassFish v3. The JSF 2.0 classes were obtained from the NetBeans JSF 2.0 bundled library.
When this book was written, the JSFUnit stable version was 1.1.0 GA. You can download this version from http://labs.jboss.com/jsfunit/downloads/. Depending on your needs, you can download:
In addition, Maven fans can download JSFUnit distributions from JBoss Maven Repository at http://repo1.maven.org/maven2. The POM declarations are:
<repositories> <repository> <id>jboss</id> <name>JBoss Repository</name> <url>http://repository.jboss.org/maven2</url> <snapshots> <enabled>false</enabled> </snapshots> </repository> </repositories> <!-- Core jar needed for all JSFUnit tests --> <dependency> <groupId>org.jboss.jsfunit</groupId> <artifactId>jboss-jsfunit-core</artifactId> <version>1.1.0.GA</version> </dependency> <!-- RichFaces and Ajax4jsf Client jar --> <dependency> <groupId>org.jboss.jsfunit</groupId> <artifactId>jboss-jsfunit-richfaces</artifactId> <version>1.1.0.GA</version> </dependency> <!-- Ant task used to "jsfunify" a WAR file --> <dependency> <groupId>org.jboss.jsfunit</groupId> <artifactId>jboss-jsfunit-ant</artifactId> <version>1.1.0.GA</version> </dependency>
Finally, you can try to access it directly from the JBoss Maven Repository at http://repository.jboss.org/maven2/org/jboss/jsfunit/.
JSFUnit 1.1.0 GA is updated to the latest beta version of JSF 2, so now you can use JSFUnit with JSF 1.1, JSF 1.2, and JSF 2.0 Beta 2. It is important to use HtmlUnit 2.5 instead of 2.4. The JSFUnit libraries (including necessary dependencies) are in the book bundle code, under the /JSF_libs/JSFUnit JSF 2.0
folder. The Xerces and Xalan distributions are required only if the container doesn't provide one or if you explicitly want to use others. These are, however, totally excluded in JBoss 5.x AS.
Next, we will develop a JSFUnit test for a basic JSF application named Working_with_JSFUnit
. For starters, we present the pure JSF application, without any JSFUnit involved. After that, we will configure the JSFUnit test, and we will make proper configurations.
Our application contains three parts as follows (the code is very simple and self explanatory, therefore no more details are provided):
… <h:form id="UserForm"> <h:outputText value="Enter your name:"/> <h:inputText value="#{userBean.firstName}" id="userId" /> <h:commandButton value="Submit" action="response?faces-redirect=true" id="submit_button"/> </h:form> …
… <h:outputText value="Inserted name:"/> <h:outputText value="#{userBean.firstName}"/> …
package users; import javax.faces.bean.ManagedBean; import javax.faces.bean.SessionScoped; @ManagedBean @SessionScoped public class UserBean { private String firstName = "Rafael Nadal"; public String getFirstName(){ return this.firstName; } public void setFirstName(String firstName){ this.firstName=firstName; } }
Now we write a JSFUnit test for the application. Conforming to the documentation (http://www.jboss.org/community/wiki/JSFUnitDocumentation), we wrote a test for the previous managed bean, as follows (in the JSFUnit API recipe, you can see more snapshots of using the JSFUnit API):
package tests; import java.io.IOException; import javax.faces.component.UIComponent; import junit.framework.Test; import junit.framework.TestSuite; import org.jboss.jsfunit.jsfsession.JSFServerSession; import org.jboss.jsfunit.jsfsession.JSFSession; public class JSFUnitTest extends org.apache.cactus.ServletTestCase { public static Test suite() { return new TestSuite( JSFUnitTest.class ); } public void testInitialPage() throws IOException { // Send an HTTP request for the initial page JSFSession jsfSession = new JSFSession("/index.xhtml"); // A JSFServerSession gives you access to JSF state JSFServerSession server = jsfSession.getJSFServerSession(); // Test navigation to initial viewID assertEquals("/index.xhtml", server.getCurrentViewID()); // Assert that the prompt component is in the //component tree and rendered UIComponent prompt = server.findComponent("userId"); assertTrue(prompt.isRendered()); // Test a managed bean assertEquals("Rafael Nadal", server.getManagedBeanValue("#{userBean.firstName}")); } }
Before we can run our test, we must configure JSFUnit in web.xml
by adding the following lines (these lines will configure JSFUnitFilter
and two servlets, ServletRedirector
and ServletTestRunner
):
<filter> <filter-name>JSFUnitFilter</filter-name> <filter-class> org.jboss.jsfunit.framework.JSFUnitFilter </filter-class> </filter> <filter-mapping> <filter-name>JSFUnitFilter</filter-name> <servlet-name>ServletTestRunner</servlet-name> </filter-mapping> <filter-mapping> <filter-name>JSFUnitFilter</filter-name> <servlet-name>ServletRedirector</servlet-name> </filter-mapping> <servlet> <servlet-name>ServletRedirector</servlet-name> <servlet-class> org.jboss.jsfunit.framework.JSFUnitServletRedirector </servlet-class> </servlet> <servlet> <servlet-name>ServletTestRunner</servlet-name> <servlet-class> org.apache.cactus.server.runner.ServletTestRunner </servlet-class> </servlet> <servlet-mapping> <servlet-name>ServletRedirector</servlet-name> <url-pattern>/ServletRedirector</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>ServletTestRunner</servlet-name> <url-pattern>/ServletTestRunner</url-pattern> </servlet-mapping>
The reports generated by JSFUnit are rendered through a stylesheet, known as cactus-report.xsl
(this is developed under the Apache Cactus project—main page at http://jakarta.apache.org/cactus/). This stylesheet can be downloaded from http://jakarta.apache.org/cactus/misc/cactus-report.xsl, and it should be placed in the /web
folder of our application.
After you complete these three steps you can deploy the application and run the test using the next URL:
http://localhost:8080/Working_with_JSFUnit/ServletTestRunner?suite=tests.JSFUnitTest&xsl=cactus-report.xsl
If everything works fine, you should be able to see something like the following screenshot:
Well, the important thing here is the part where we run the test. Notice that the test is executed through a servlet named ServletTestRunner
that gets two parameters as follows:
suite
: The value of this parameter represents the fully qualified name of the JSFUnit test class.xsl
: The value of this parameter represents the name of an XSLT (EXtensible Stylesheet Language Transformations) document (in our case the cactus-report.xsl
).The hardest part about using JSFUnit is preparing your WAR, since the configuration steps are slightly different depending on the platform used. At http://www.jboss.org/community/wiki/GettingStartedGuide page you can find a simple JSFUnit example (including the code) for the following platforms: