Unit Testing JSF with Mock Objects

I’ve seen some discussions on the unit testing business with JSF and questions are mainly focused on the testing of managed beans, converters, validators and other stuff. Most of the business logic is generally located in managed beans and since these beans are actually ordinary java POJOs, I dont think it is too hard to figure out the way for testing. The tricky parts may be the ones where JSF stuff like FacesContext is involved.

In one of my previous entries, I’ve shown a way to make the backing beans of the pages aware of the JSF lifecycle. Each backing bean implementing ILifeCycleAware can execute it’s code at several phases of the lifecycle like onPageLoad, onPreValidations and etc. In summary the idea is simple, from the view id, say index.jsp, the managed bean name, Index is extracted and casted to ILifeCycleAware, later phaselisteners execute the methods like onPageLoad and etc. Refer to my old post to learn more about the idea and going further with the testing of it.

In order to provide more features like these to the developers in my project, I’ve extended this solution to provide two extra methods; onPreValidations and onPreRender. After adding these two methods to the ILifeCycleAware interface, I’ve written the tests of this functionality. The testing scenario and the environment may seem tricky to create since there are phaselisteners, phaseevents, a request for a page, facescontext and other stuff involved but in the end it is so fun and easy to test these buddies with mocks. Here is the tester class;

  
    
    

public class LifeCycleListenerTester extends MockObjectTestCase{

    private PageLoadPhaseListener pageLoadPhaseListener;
    
    private PreValidationsPhaseListener preValidationsPhaseListener;
    
    private PreRenderPhaseListener preRenderPhaseListener;
    
    Mock mockManagedBean;      //dynamic mock
    
    MockFacesContext facesContext;  //static mock
    
    protected void setUp() {
      pageLoadPhaseListener = new PageLoadPhaseListener();
      preValidationsPhaseListener = new PreValidationsPhaseListener();
      preRenderPhaseListener = new PreRenderPhaseListener();
      
      mockManagedBean = new Mock(ILifeCycleAware.class);
      Object proxyManagedBean = mockManagedBean.proxy();
      
      pageLoadPhaseListener.setManagedBean(proxyManagedBean);
      preValidationsPhaseListener.setManagedBean(proxyManagedBean);
      preRenderPhaseListener.setManagedBean(proxyManagedBean);
      facesContext = new MockFacesContext();
      UIViewRoot viewRoot = new UIViewRoot();
      viewRoot.setViewId(“/darthmaul.jsp”);
      facesContext.setViewRoot(viewRoot);
    }
    
    public void testOnLoadEventIsCalledAfterRestoreView() {
      PhaseEvent phaseEvent = new PhaseEvent(facesContext, PhaseId.RESTORE_VIEW, new LifecycleImpl());
      mockManagedBean.expects(once()).method(“onPageLoad”);
      pageLoadPhaseListener.afterPhase(phaseEvent);
    }
    
    public void testPreValidationsEventIsCalledBeforeValidations() {
      PhaseEvent phaseEvent = new PhaseEvent(facesContext, PhaseId.PROCESS_VALIDATIONS, new LifecycleImpl());
      mockManagedBean.expects(once()).method(“onPreValidations”);
      preValidationsPhaseListener.beforePhase(phaseEvent);
    }
    
    public void testPreRenderEventIsCalledBeforeRenderResponse() {
      PhaseEvent phaseEvent = new PhaseEvent(facesContext, PhaseId.RENDER_RESPONSE, new LifecycleImpl());
      mockManagedBean.expects(once()).method(“onPreRender”);
      preRenderPhaseListener.beforePhase(phaseEvent);
    }
  }     

There are two mock objects here, the dynamic one is the managed bean implementing the ILifeCycleAware bean. I  set an expectation on it to test whether the life cycle methods are called or not. MockFacesContext is a static mock class and used whenever a faces context instance is needed during testing. In this case it is used setting a dummy viewroot with a view id and creating a phaseevent for a phaselistener. Shale has also filled this gap in JSF testing and provided a static mock library for classes like FacesContext, ViewHandler, ExternalContext and etc. Well, there was no Shale when the project I’m working for started so we’ve created our own static mock library. But now I’d to use the shale’s library containing the mock implementations for testing purposes instead of creating my own.

This was just an example to show how testing could be done with JSF, with the Mock cousins of the real JSF stuff you can easily create the testing scenarios where your phaselisteners, converters, validators, managed beans, resolvers, view  handlers, navigation handlers and anything else handlers face with.

One Response to Unit Testing JSF with Mock Objects

  1. Interesting,

    this moring I started on JMock for some *more* intelligent stuff. I created a patch for Shale and JMock support

    http://issues.apache.org/struts/browse/SHALE-210

    -Matthias

%d bloggers like this: