我很难在我的JSF支持bean类上实现单元测试...例如,一些方法使用会话或请求参数,使用这种代码获得:
FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("paramKey");
。
我的问题是:如何测试从会话或请求中获取值的方法?
答案 0 :(得分:9)
我通常做的是避免将静态方法调用到我想要测试的bean中。这意味着您当前的代码将被重构:
FacesContext.getCurrentInstance().getExternalContext()
.getSessionMap().get("paramKey");
有没有办法用静态方法调用来测试它们?可能有,但他们给我带来了很多麻烦而不是帮助。所以最后我摆脱了它们并改变了我的设计。让第二个豆做它(你稍后会嘲笑)。在您的情况下,创建一个管理该功能的@SessionScoped
bean:
@ManagedBean
@SessionScoped
public class SessionBean{
public Object getSessionParam(String paramKey){
FacesContext.getCurrentInstance().getExternalContext()
.getSessionMap().get(paramKey);
}
}
并在需要它的每个bean中注入该bean(我通常从拥有它的抽象bean扩展我的视图/请求bean,因此不必在每个bean中实现它):
@ManagedBean
@RequestScoped
public class RequestBean{
@ManagedProperty(value="#{sessionBean}")
private SessionBean sessionBean;
public void accessSessionParam(){
sessionBean.getSessionParam("name");
}
}
通过辅助SessionBean
,您可以轻松访问静态方法。那么,如何测试呢?只需创建一个模拟(例如,使用Mockito):
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
}
}
答案 1 :(得分:6)
这是possible to mock FacesContext
,但这不太理想。 Mockito示例:
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;
}
}
如果您的平台支持它,则首选CDI到JSF托管bean。 CDI具有静态依赖性检查并注入代理以防止范围泄漏。 CDI不支持JSF的所有功能,但在必要时connect JSF managed beans to CDI相对容易。
JSF托管bean限制了您将类型注入的范围,但即使这样也会导致范围泄漏。例如,即使对象属于请求范围#{sessionScope}
,也可以将ExternalContext
变量注入会话范围bean。可以通过writing your own JSF bean proxies克服此问题。
注意:大部分内容都是用Java EE 6编写的; Java EE 7可能会改进。