如何测试使用会话参数的JSF bean方法?

Fel*_*eis 8 jsf unit-testing

我正在努力在我的JSF支持bean类上实现单元测试...例如,一些方法使用会话或请求参数,使用这种代码获得:

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

我的问题是:如何测试从会话或请求中获取值的方法?

Xtr*_*ica 9

我通常做的是避免将静态方法调用到我想测试的bean中.这意味着您当前的代码将被重构:

FacesContext.getCurrentInstance().getExternalContext()
    .getSessionMap().get("paramKey");
Run Code Online (Sandbox Code Playgroud)

有没有办法用静态方法调用来测试它们?可能有,但他们给我带来了很多麻烦而不是帮助.所以最后我摆脱了它们并改变了我的设计.让第二个豆做它(你稍后会嘲笑).在您的情况下,创建一个@SessionScoped管理该功能的bean:

@ManagedBean
@SessionScoped
public class SessionBean{

    public Object getSessionParam(String paramKey){
        FacesContext.getCurrentInstance().getExternalContext()
           .getSessionMap().get(paramKey);
    }

}
Run Code Online (Sandbox Code Playgroud)

并在需要它的每个bean中注入该bean(我通常从拥有它的抽象bean扩展我的视图/请求bean,因此不必在每个bean中实现它):

@ManagedBean
@RequestScoped
public class RequestBean{

    @ManagedProperty(value="#{sessionBean}")
    private SessionBean sessionBean;

    public void accessSessionParam(){
        sessionBean.getSessionParam("name");
    }

}
Run Code Online (Sandbox Code Playgroud)

这样您就可以通过辅助设备轻松访问静态方法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
    }

}
Run Code Online (Sandbox Code Playgroud)


McD*_*ell 6

这是可能的嘲笑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;
  }
}
Run Code Online (Sandbox Code Playgroud)

如果您的平台支持它,则更喜欢CDI到JSF托管bean.CDI具有静态依赖性检查并注入代理以防止范围泄漏.CDI不支持JSF的所有功能,但在必要时将JSF托管bean连接到CDI相对容易.

JSF托管bean限制了您将类型注入的范围,但即使这样也会导致范围泄漏.例如,#{sessionScope}即使对象属于请求作用域,也可以将变量注入会话作用域bean ExternalContext.可以通过编写自己的JSF bean代理来克服这个问题.

注意:大部分内容都是用Java EE 6编写的; Java EE 7可能会改进一些东西.