I am trying to add some unit tests to a JSF application. This application didnt rely heavily on any best practices, so many service methods use the FacesContext
to
This url provides a really good article on it: http://illegalargumentexception.blogspot.com/2011/12/jsf-mocking-facescontext-for-unit-tests.html
You have your managed bean:
package foo;
import java.util.Map;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
import javax.faces.context.FacesContext;
@ManagedBean
@RequestScoped
public class AlphaBean {
public String incrementFoo() {
Map session = FacesContext.getCurrentInstance()
.getExternalContext()
.getSessionMap();
Integer foo = (Integer) session.get("foo");
foo = (foo == null) ? 1 : foo + 1;
session.put("foo", foo);
return null;
}
}
You stub out the FacesContext:
package foo.test;
import javax.faces.context.FacesContext;
import org.mockito.Mockito;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
public abstract class ContextMocker extends FacesContext {
private ContextMocker() {
}
private static final Release RELEASE = new Release();
private static class Release implements Answer {
@Override
public Void answer(InvocationOnMock invocation) throws Throwable {
setCurrentInstance(null);
return null;
}
}
public static FacesContext mockFacesContext() {
FacesContext context = Mockito.mock(FacesContext.class);
setCurrentInstance(context);
Mockito.doAnswer(RELEASE)
.when(context)
.release();
return context;
}
}
Then write your unit test:
@Test
public void testIncrementFoo() {
FacesContext context = ContextMocker.mockFacesContext();
try {
Map session = new HashMap();
ExternalContext ext = mock(ExternalContext.class);
when(ext.getSessionMap()).thenReturn(session);
when(context.getExternalContext()).thenReturn(ext);
AlphaBean bean = new AlphaBean();
bean.incrementFoo();
assertEquals(1, session.get("foo"));
bean.incrementFoo();
assertEquals(2, session.get("foo"));
} finally {
context.release();
}
}