How to test JSF bean methods that use session parameters?

I find it difficult to run unit tests in my bean support classes for JSF ... For example, some of the methods use session or query parameters obtained with this type of code:

FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("paramKey"); .

My question is: how can I test a method that gets values ​​from a session or request?

+6
source share
2 answers

What I usually do is to avoid calling static methods in beans, which I want to test . This means that your current code needs to be reorganized:

 FacesContext.getCurrentInstance().getExternalContext() .getSessionMap().get("paramKey"); 

Are there any ways to test them with my static method calls? Probably there is, but they led me to more trouble than help. Therefore, in the end I got rid of them and changed my design. Just let the second bean do it (which you will mock later). In your case, create an @SessionScoped bean that controls this functionality:

 @ManagedBean @SessionScoped public class SessionBean{ public Object getSessionParam(String paramKey){ FacesContext.getCurrentInstance().getExternalContext() .getSessionMap().get(paramKey); } } 

And add this bean to each individual bean that it needs (I usually extend my view / request beans from the abstract bean that has it, so I don't need to implement it in every bean):

 @ManagedBean @RequestScoped public class RequestBean{ @ManagedProperty(value="#{sessionBean}") private SessionBean sessionBean; public void accessSessionParam(){ sessionBean.getSessionParam("name"); } } 

This way, you can easily access static methods using the helper SessionBean . Then how to check it? Just create a layout (using Mockito , for example):

 public class Test{ public void test1(){ SessionBean sb = Mockito.mock(SessionBean.class); //Mock your 'getSessionParam' method ValueBean vb = new ValueBean(); Mockito.when(sb.getSessionParam(Mockito.anyString()).thenReturn(vb); //Create your bean to test and set your mock to it RequestBean rb = new RequestBean(); rb.setSessionBean(sb); //here you can test your RequestBean assuming //sessionBean.getSessionParam() //will return vb for every single call } } 
+8
source

It's possible to make fun of FacesContext , but it's less than ideal. Mockito example:

 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<Void> { @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; } } 

If your platform supports it, prefer CDI to managed JSF beans. CDI has a static dependency check and injects proxies to prevent area leakage. CDI does not support all JSF features, but it is relatively convenient to connect JSF-managed beans to CDI where necessary.

JSF-managed beans restricts the scope into which you type, but even this can lead to leakage of the scope. For example, the variable #{sessionScope} can be entered into the bean session scope, although the object belongs to the ExternalContext request scope. This can be overcome by writing your own JSF bean proxies .

Note: most of this is written with Java EE 6 in mind; things may have improved with Java EE 7.

+6
source

Source: https://habr.com/ru/post/950472/


All Articles