EDIT: Cleaned up the question for readability. Please ignore comments up to October 31st.
In our application stack we work with many smaller jar modules that get combined into a final web application. One module defines JSF features, like implementing this ViewScope.
Now appart from integration testing we want to be able to unit test every part and thus need a way to mock a complete Faces Context (to be accessed via a wrapper) to test classes that use it.
The important part here is complete meaning it has to have an initialized ViewMap
as this is where our ViewScope
puts its objects.
I've tried different approaches:
1) shale-test: I've come the furthest with this but unfortunately the project is retired.
So far I've wrapped the FacesContext in a Provider which allows me to replace it with a Mocked FacesContext for testing. I've also modified the shale implementation of AbstractViewControllerTestCase to include an application context.
However when calling MockedFacesContext.getViewRoot().getViewMap()
as this will throw an UnsupportedOperationException
. The reasons seems to be that the MockApplication does not instantiate Application.defaultApplication (it's null) which is required for this method call. This seems to be a shale-test limitation.
2) JMock or mockito These seem to me not to not really mock anything at all as most members will just remain null. Don't know if JMock or mockito can actually call the propper initialization methods.
3) Custom Faces Mocker: To me this seems the only remaining option but we don't really have the time to analyse how Faces is initialized and recreate the behaviour for mocking purposes. Maybe someone has dont this before and can share major waypoints and gotchas?
Or is there any alternative way to mock a FacesContext outside a web application?
I would go with PowerMock+Mockito:
From your link:
private Map<String,Object> getViewMap() {
return FacesContext.getCurrentInstance().getViewRoot().getViewMap();
}
In the test:
@RunWith(PowerMockRunner.class)
@PrepareForTest({ FacesContext.class });
public class TheTest {
/*
* fake viewMap.
*/
private Map<String,Object> viewMap = Maps.newHashMap() // guava
/**
* mock for FaceContext
*/
@Mock
private FacesContext faceContext;
/**
* mock for UIViewRoot
*/
@Mock
private UIViewRoot uiViewRoot;
@Before
public void setUp() {
Mockito.doReturn(this.uiViewRoot).when(this.faceContext).getViewRoot();
Mockito.doReturn(this.viewMap).when(this.uiViewRoot).getViewMap();
PowerMock.mockStatic(FacesContext.class);
PowerMock.doReturn(this.faceContext).when(FacesContext.class, "getCurrentInstance");
}
@Test
public void someTest() {
/*
* do your thing and when
* FacesContext.getCurrentInstance().getViewRoot().getViewMap();
* is called, this.viewMap is returned.
*/
}
}
Some reading: