WorkingWithStubs

Version 17

    The stub library is a port of the Shale Test Framework.  The only major difference is that the word "mock" has been replaced with "stub", see Mocks Aren't Stubs for why this decision was made. 

     

    The base of the stub library is org.jboss.jsfunit.stub.base.AbstractJsfTestCase.  By extending this class you get the following behavior.

    %%(color:green)

       public class ConcreteJsfTestCase extends AbstractJsfTestCase {
    
         public ConcreteJsfTestCase() {
              super(ConcreteJsfTestCase.class.getName());
         }
    
         public void testIdentity() {
              
              assertSame(this.facesContext, FacesContext.getCurrentInstance());
              
              assertSame(this.facesContext.getApplication(), this.application);
              
              assertSame(this.facesContext.getExternalContext().getContext(), this.servletContext);
              
              assertSame(this.facesContext.getRenderKit(), this.renderKit);
              
              assertSame(this.externalContext.getSession(false), this.session);
              
              Integer five = new Integer(5);
              request.setAttribute("five", five);
              
              assertSame(five, this.externalContext.getRequestMap().get("five"));
              
         }
         
       }
    

    %%

    Essentially the AbstractJsfTestCase provides a stubbed out JSF environment.  The fields inherited provide the fundamental building blocks of the JSF and Servlet APIs. 

     

    This gives us the ability to test how components render themselves, outside of a container.

    %%(color:green)

       public class RenderTest extends AbstractJsfTestCase {
    
         protected UIInput component;
         protected ResponseWriterStub writer ;
         
         public RenderTest() {
              super(RenderTest.class.getName());
         }
         
         protected void setUp() throws Exception {
    
              super.setUp();
              
              component = new HtmlInputText();
              writer = new ResponseWriterStub(new StringWriter(), null, null);
              facesContext.setResponseWriter(writer);
              facesContext.getRenderKit().addRenderer(
                        component.getFamily(),
                        component.getRendererType(),
                        new HtmlTextRenderer());
         }
    
         public void testRender() throws Exception {
    
              component.setValue("99");
    
              // simulating the render response phase
              component.encodeAll(facesContext);
                    assertTrue(writer.getWriter().toString().contains("99"));
    
         }
    
       }
    

    %%

    Notice that in the testRender method of the RenderTest we are explicitly setting the component value.  To demonstrate more of what the stub library can do, let's override this behavior.

    %%(color:green)

       public class ConverterTest extends RenderTest {
    
         public void testRender() throws Exception {
    
              // component.setValue("99");
              request.setAttribute("scoped", new Integer(99));
              component.setValueBinding("value", 
                        application.createValueBinding("#{scoped}"));
              
              component.setConverter(new IncrementConverter());
              
              component.encodeAll(facesContext);
              assertTrue(writer.getWriter().toString().contains("100"));
    
         }
         
       }
    

    %%

    In ConverterTest the component value is set via an EL expression rather than a String literal.  It is important to note that this expression is evaluated within your test suite, just as it would inside a container. 

     

    In all of the examples you've seen so far the components and/or renderers are being programmatically wired together.  Nothing wrong with that, but another option is to have the stub library parse your JSF deployment descriptor by making use of the ConfigParser.

    %%(color:green)

       public class ConverterTest2 extends RenderTest {
    
         public void testRender() throws Exception {
    
              // component.setValue("99");
              request.setAttribute("scoped", new Integer(99));
              component.setValueBinding("value", 
                        application.createValueBinding("#{scoped}"));
              
              //component.setConverter(new IncrementConverter());
              URL url = getClass().getResource("/org/jboss/jsfunit/stub/demo/faces-config.xml");
              new ConfigParser().parse(url);
              component.setConverter(application.createConverter("incrementConverter"));
              
              component.encodeAll(facesContext);
              assertTrue(writer.getWriter().toString().contains("100"));
    
         }
    
       }
    

    %%

     

    Your JSF configuration file would look something like this with above TestCase.

    %%(color:green)

      <faces-config>
    
        <converter>
          <converter-id>incrementConverter</converter-id>
          <converter-class>
               org.jboss.jsfunit.stub.demo.IncrementConverter
          </converter-class>
        </converter>
    
      </faces-config>
    
    

    %%