First, always follow the JSFUnit Golden Rule: Use Component ID's

For every JSF component on a page, you have the option of providing a component ID. If you don't provide one, JSF will create one for you. However, if you let JSF create the ID, you will have a hard time referencing the component in your tests. So at least use an ID for any component that you might want to test.

For Example:

	  <h:inputText value="#{foo.text}" id="input_foo_text"/>
	

Create a JSP or Facelets page

	

<f:view>  
   <h:form id="form1">    
      
     <h:outputText value="Enter your name:" rendered="#{empty foo.text}" id="prompt"/>
     <h:outputText value="Hello #{foo.text}" rendered="#{!empty foo.text}" id="greeting"/>
      
     <h:inputText value="#{foo.text}" id="input_foo_text"/>
     <h:message for="input_foo_text" styleClass="errorMessage"/>
     <br/>
     <h:commandButton value="Submit" action="/index.jsp" id="submit_button"/>
     <h:commandButton value="Goodbye" action="/finalgreeting.jsp" id="goodbye_button"/>

   </h:form>
</f:view>


Create a JUnit test using the JSFUnit API

Note that your test should extend ServletTestCase. The full JSFUnit javadoc is here.

 

	

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.faces");
      
      // A JSFClientSession emulates the browser and lets you test HTML
      JSFClientSession client = jsfSession.getJSFClientSession();
      
      // A JSFServerSession gives you access to JSF state      
      JSFServerSession server = jsfSession.getJSFServerSession();

      // Test navigation to initial viewID
      assertEquals("/index.jsp", server.getCurrentViewID());

      // Assert that the prompt component is in the component tree and rendered
      UIComponent prompt = server.findComponent("greeting");
      assertTrue(prompt.isRendered());

      // Test a managed bean
      assertEquals("Stan", server.getManagedBeanValue("#{foo.text}"));
   }
}

 


Add this to your web.xml

If you are using a Servlet 3.0 container such as JBoss AS6 you can skip this step.  Click Here for details.

	

   <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>

 


Package these jars in your WEB-INF/lib

First, you will need the JSFUnit jar. Since JSFunit uses JUnit, Cactus, HtmlUnit, and HttpUnit for much of its infrastructue, you will need at least the minimum jars for these frameworks as well. Don't worry, you won't need to pollute your project with these dependencies. JSFUnit Documentation shows how to use Ant or Maven to only include these extra jars when you are testing.

Here are the jars you will need in your WEB-INF/lib. Some of these jars will not be needed if your container or application already provides them.

If not already included in your container, you will also need xerces and xalan. If already installed, you should prefer the container's installed version. You should never include these jars in your WAR if you are running JBoss AS 5.x or 6.x.

Include cactus-report.xsl in the root of your WAR

You can get cactus-report.xsl here. This is usually placed in the root of the WAR. 

If you are using a Servlet 3.0 container then you don't need to do this.  cactus-report.xsl will be available at /jsfunit/cactus-report.xsl.

Deploy your application and run the tests.

Deploy your JSF application to your favorite server. Then, type something like the following URL into your browser to run the tests:

           http://localhost:8080/myjsfapp/ServletTestRunner?suite=com.foo.JSFUnitTest&xsl=cactus-report.xsl   

If you are using a Servlet 3.0 container such as JBoss AS6 you should use the JSFUnit console instead of typing the URL manually.  Click Here for details.

The ServletTestRunner will run your tests with JUnit and display the results in your browser. When you are done, the output will look something like this:

Running JSFUnit tests as part of your build.

After you see how to run JSFunit tests from a browser, you will probably want to integrate JSFUnit as part of your build and part of a true Test-Driven Development process. We have docs for Maven and Ant linked from this wiki page.

Since the JSFUnit infrastructure is based on Apache Cactus, you can set up your tests to run in any way supported by Cactus. The only difference is that you use the web.xml declarations as shown above.

View or run a working example.

Example WARS pre-built for many different containers can be downloaded from this wiki page.