Published using Google Docs
Test JSF applications with embedded container.
Updated automatically every 5 minutes

Test JSF Applications with Embedded Server

Preface

JSF is very complicated framework, with a lot of tight related components, that makes testing pretty complicated. It runs inside Servlet container, and framework behavior depends from container configuration. The goal of embedded servlet container is providing flexible test environment suitable to test parts of JSF application: Composite components, view fragments and templates. The idea is very similar to Jboss Arquilian framework, with some JSF-specific extensions. The main answer to the question why to not use Arquillian to test RichFaces components is what it was introduced far before  Jboss implementation. Another answer is JSF-specific features and speed, embedded stage server runs much faster real implementations.

Features

Limitations

Usage

Instantiation of FacesEnvironment

jUnit 4 test class fragment:

private FacesEnvironment environment;

@Before

public void setUp() {

        environment = FacesEnvironment.createEnvironment().start();

}

@After

public void thearDown() throws Exception{

     environment.release();

}

This code creates an instance of environment, initializes JSF framework and starts server instance before each test, and releases resources after test. The version of this method with ApplicationServer parameter lets create environment for different server implementation ( currently, embedded Jetty server supported ).

Configuration

FacesEnvironment class has set of configuration methods to describe web application context and setup server. all methods returns back the same instance, so they can be chained:

withContent(String,String) - define content of web resource for given path:

        environment = FacesEnvironment.createEnvironment().withContent("/test.xhtml",

                "<html xmlns=\"http://www.w3.org/1999/xhtml\"\n" +

                        "      xmlns:ui=\"http://java.sun.com/jsf/facelets\"\n" +

                        "      xmlns:h=\"http://java.sun.com/jsf/html\">"+

                        "<h:form id=\"helloForm\" >"+

                "    <h:outputText value=\"foo_bar\" />\n" +

                        "</h:form>\n" +

                        "</html>").start();

withResource(String,String) - put content of classpath resource to the given path in servlet context.

withWebRoot(String) - create virtual web server context from the package containing given resource. Suitable to create web application fragment from resources stored in the jar. Another way to create vitrual servlet context is system property ‘webroot’, that should contain path to the folder with web application content.

withResourcesFromDirectory(String path, URL resource) - Add all resources from the directory to the virtual web application content. Only 'file' or 'jar' protocols are supported. If this parameter points to a file, it will be converted to a enclosing directory.

withInitParameter(String name, String value) - add ServletContext initialization parameter to value.

withFilter(String name, Filter filter) - add filter in front of FacesServlet.

Additional configuration can be performed directly on the ApplicationServer instance, see JavaDoc for details.

Performing request

To perform JSF request, call environment.createFacesRequest(String url) method:

    @Test

    public void testRequest() throws Exception {

        FacesRequest request = environment.createFacesRequest("http://localhost/test.jsf");

        assertNotNull(request.execute());

        String contentAsString = request.getConnection().getContentAsString();

        assertTrue(contentAsString.contains(ResponseStateManager.VIEW_STATE_PARAM));

    }

This method gets request URL and returns FacesRequest object, that allows additional configuration ( adding request parameters, cookies, headers ). The request is not active until start() or execute() methods callled. execute() method performs whole request cycle, while start() only initialized request, created FacesContext and returns, that allows test to execute Faces Lifecycle directly inside request context.

FacesRule

FacesRule is jUnit 4 MethodRule that invoked around every test method. It automatically configures and starts converter before method and shut down it after. Using method rule allows to combine with another rules ot test runners - jsf-test MockRunner, Mockito runner, parametrised tests. There is fragment of test that creates mock instances of Jsf beans and run facelets fragment with user registration form, using mock objects for  ‘facade’ and ‘user’ beans:

@RunWith(MockitoJUnitRunner.class)

public class RegisterTest implements ServletRequestListener{

        @Rule

        public FacesRule rule = HtmlUnitRule.create().withResource("/registerTest.xhtml", "registerTest.xhtml").withListener(this);

        @Mock

        Facade facade;

        @Mock

        User user;

        @Before

        public void setUp() throws Exception {

                rule.setSessionAttribute(“facade”, facade);

        }

        public void requestInitialized(ServletRequestEvent sre) {

                sre.getServletRequest().setAttribute(“user”, user);                

        }

registerTest.xhtml only includes registration form fragment by <ui:include> directive. Therefore, this test lets check functionality of the single fragment without having real EJB for facade, database, and without inference from other parts of application.

Embedded Jetty

If tests have to be run in the real container, jsf-test project contains the code that lets to use embedded Jetty server in FacesEnvironment. To enable it, just add jsf-test-jetty.jar to the project:

<dependency>

   <groupId>org.jboss.test-jsf</groupId>

   <artifactId>jsf-test-jetty</artifactId>

</dependency>

Now, you can put server implementation instance to the FacesEnvironment constructor or factory method:

FacesEnvironment.create(new org.jboss.test.faces.jetty.JettyServer())

 Optional argument for JettyServer constructor is the port number where server is listening for requests, default is 8880.

The server parses web.xml and other configuration files. Web application runs in its own context, and serves requests in the separate thread, so access to bean instances and partial requests not available in this case.