Injection for JSFSession, JSFClientSession, and JSFServerSession

Version 16

    As of JSFUnit release 2.0.0, you can use Arquillian instead of Catus to run your tests.  This also allows you to use JUnit 4 and TestNG instead of JUnit 3.  It also allows you to use JSFUnit annotations for dependency injection.

     

    Injecting JSFSession, JSFClientSession, and JSFServerSession into your test method

    It is very easy to inject one or more or the above JSFUnit objects into your test.  Here is an example:

    @Test
    @InitialPage("/index.faces")
    public void testGetCurrentViewId(JSFServerSession server)   {
       Assert.assertEquals("/index.jsp", server.getCurrentViewID());
       Assert.assertEquals(server.getCurrentViewID(), server.getFacesContext().getViewRoot().getViewId());
    }

    The only required annotation is the @InitialPage.  But there are others (described later) if you need them.

     

    Note the differences between using injection and the traditional JSFUnit code.  In the past, you would need to manually create a JSFSession and then get a handle to the JSFServerSession like this:

    JSFSession jsfSession = new JSFSession("/index.faces");
    JSFClientSession client = jsfSession.getJSFClientSession();
    

    You can still use this old boilerplate code if you prefer.

     

    You can inject any combination of the JSFSession, JSFServerSession, and JSFClientSession.  They are all related to each other and bound to your HttpSession.  But you only need to specify the ones you will use.

    @Test
    @InitialPage("/index.faces")
    public void testSetParamAndSubmit(JSFClientSession client, JSFServerSession server) throws IOException
    {
       client.setValue("input_foo_text", "Stan");
       client.click("submit_button");
       UIComponent greeting = server.findComponent("greeting");
       Assert.assertTrue(greeting.isRendered());
    }
    

     

    Injecting JSFSession, JSFClientSession, and JSFServerSession into instance variables

    If all of your test methods use the same @InitialPage you can declare this at the class level and inject your JSFUnit objects as instance variables.

    @RunWith(Arquillian.class)
    @InitialPage("/index.faces")
    public class FacadeAPITest
    {
       private @JSFUnitResource JSFSession jsfSession;
       private @JSFUnitResource JSFClientSession client;
       private @JSFUnitResource JSFServerSession server;
    
       @Test
       public void MyFirstTest() {
          // use instance variables above
       }
    
       @Test
       public void MySecondTest() {
          // Instance variables will be reinitialized so
          // MySecondTest will get a new instance of
         //  jsfSession, client, and server
       }
    }
    

    ** Note:  It's probably not a good idea to mix method injection with instance variable injection.  If you use both in the same test class you might get unexpected results.

     

    Setting an InitialRequestStrategy with @InitialRequest

    Sometimes you need to do some special setup before the first request.  JSFUnit's answer for this is to let you set your own InitialRequestStrategy.  You can use the @InitialRequest annotation to specify a class with a no-arg constructor that implements the org.jboss.jsfunit.framework.InitialRequestStrategy interface.  This example sets a custom value for socket timeout.

    @Test
    @InitialPage("/index.faces")
    @InitialRequest(SetSocketTimeoutRequestStrategy.class)
    public void testInitialRequestAnnotation(JSFSession jsfSession)   {      
       // timeout set to 10001 in SetSocketTimeoutRequestStrategy
       Assert.assertEquals(10001, jsfSession.getWebClient().getTimeout());
    }
    

    Click Here for source code of SetSocketTimeoutRequestStrategy.

     

    The @BasicAuthentication annotation

    Sometimes you need to get past some authentication in your initial request.  JSFUnit ships with two InitialRequestStrategy implementations to help with this.  The @BasicAuthentication annotation uses the BasicAuthenticationStrategy.  Also see Testing Secure Pages.

    @Test
    @InitialPage("/secured-page.faces")
    @BasicAuthentication(userName="admin", password="password")
    public void testBasicAuth(JSFServerSession server, JSFClientSession client) throws IOException   {
       Assert.assertEquals("/secured-page.jsp", server.getCurrentViewID());
       Assert.assertTrue(client.getPageAsText().contains("Welcome to the Basic Secured Application Page"));
    }

     

    The @FormAuthentication annotation

    The @FormAuthentication annotation uses the FormAuthenticationStrategy.  Required parameters are userName, password, and submitComponent.  userNameComponent and passwordComponent are optional and will default to the standard JEE component names of j_username and j_password, respectively.  See Testing Secure Pages for more in-depth information.

    @Test
    @InitialPage("/form-secured-page.faces")
    @FormAuthentication(userName="admin",
                        password="password",
                        submitComponent="login_button",
                        userNameComponent="j_username",
                        passwordComponent="j_password")
    public void testFormAuthNonStandard(JSFServerSession server, JSFClientSession client) throws IOException   {
       Assert.assertEquals("/form-secured-page.jsp", server.getCurrentViewID());
       Assert.assertTrue(client.getPageAsText().contains("Welcome to the Form Secured Application Page"));
    }

     

    ** Note: @InitialRequest, @BasicAuthentication, and @FormAuthentication all set an instance of the InitialRequestStrategy interface.  Only one of these annotations are allowed per test method and/or per test class.

     

    The @Proxy annotation

    If you need to set the proxy host and port, you can do so with the @Proxy annotation:

    @Test
    @InitialPage("/index.faces")   
    @Proxy(host = "localhost", port = 8080)
    public void testSetProxy(JSFSession jsfSession) throws IOException   {   
       Assert.assertEquals("localhost", jsfSession.getWebClient().getProxyConfig().getProxyHost());
       Assert.assertEquals(8080, jsfSession.getWebClient().getProxyConfig().getProxyPort());
    }
    

     

    The @Browser annotation

    JSFUnit uses HtmlUnit to simulate a browser session.  HtmlUnit is capable of emulating several different browsers.  You can set which browser you want to emulate using the @Browser annotation.  This annotation requires that you pass in an instance of JSFUnit's BrowserVersion enum.  Note that JSFUnit's Browser enum is a wrapper for HtmlUnit's BrowserVersion class.

    @Test
    @InitialPage("/index.faces")
    @BrowserVersion(org.jboss.jsfunit.cdi.Browser.INTERNET_EXPLORER_6)   
    public void testCustomBrowserVersion(JSFSession jsfSession) throws IOException   {
       Assert.assertEquals(com.gargoylesoftware.htmlunit.BrowserVersion.INTERNET_EXPLORER_6,
                                     jsfSession.getWebClient().getBrowserVersion());      
    }

     

    The @Cookies annotation

    Sometimes you need to set a some cookies for the duration of your JSFSession.  You can use the @Cookies annotation for this.  Note that there is a one-to-one correspondence between the name/value pairs.

    @Test
    @InitialPage("/index.faces")
    @Cookies(names = {"cookie1", "cookie2"},
             values = {"value1", "value2"})
    public void testCustomCookies(JSFClientSession client, JSFServerSession server) throws IOException   {
       Assert.assertEquals("value1", getCookieValue(server, "cookie1"));
       Assert.assertEquals("value2", getCookieValue(server, "cookie2"));
        // verify that cookies survive for the whole session
       client.click("submit_button");
       Assert.assertEquals("value1", getCookieValue(server, "cookie1"));
       Assert.assertEquals("value2", getCookieValue(server, "cookie2"));
    }
    
    private String getCookieValue(JSFServerSession server, String cookieName)   {
       Object cookie = server.getFacesContext()
                             .getExternalContext()
                             .getRequestCookieMap()
                             .get(cookieName);
       if (cookie != null) return ((Cookie)cookie).getValue();
       return null;
    }