【问题标题】:JSF - JUnit FacesContext mock TestJSF - JUnit FacesContext 模拟测试
【发布时间】:2013-10-16 07:21:32
【问题描述】:

我的 JSF 应用程序的 wirint 测试用例有一些问题。所以我想测试我的注销方法:

            FacesContext context = EasyMock.createMock(FacesContext.class);
            String userName = "testUserName";
            HttpSession session = EasyMock.createMock(HttpSession.class);
            ExternalContext ext = EasyMock.createMock(ExternalContext.class);
            EasyMock.expect(ext.getSession(true)).andReturn(session);
            EasyMock.expect(context.getExternalContext()).andReturn(ext).times(2);
            context.getExternalContext().invalidateSession();
            EasyMock.expectLastCall().once();           

            EasyMock.replay(context);
            EasyMock.replay(ext);
            EasyMock.replay(session);

            loginForm = new LoginForm();
            loginForm.setUserName(userName);
            String expected = "login";
            String actual = loginForm.logout();
            context.release();

            Assert.assertEquals(expected, actual);
            EasyMock.verify(context);
            EasyMock.verify(ext);
            EasyMock.verify(session);

我的注销方法是:

    public String logout() {
        FacesContext.getCurrentInstance().getExternalContext().invalidateSession();
        return "/authentication/login.xhtml?faces-redirect=true";
    }

我的问题是我在这里遇到了一个空指针异常: EasyMock.expectLastCall().once() 应该如何正确测试?我想这是模拟的问题,但我找不到解决方案,在这种情况下我怎么能正确模拟 FacesContext

【问题讨论】:

  • 为什么要测试logout()?它没有逻辑,只使用来自 javax.faces 的方法(您应该假设开发它的团队已经正确测试了这些方法)。

标签: java jsf jsf-2 junit easymock


【解决方案1】:

为了完成上述工作,您可以使用例如 PowerMock,它是一个框架,可让您扩展模拟库,例如具有额外功能的 EasyMock。在这种情况下,它允许您模拟 FacesContext 的静态方法。

如果您使用的是 Maven,请使用以下 link 检查所需的依赖项设置。

使用这两个注释来注释您的 JUnit 测试类。第一个注释告诉 JUnit 使用 PowerMockRunner 运行测试。第二个注释告诉 PowerMock 准备模拟 FacesContext 类。

@RunWith(PowerMockRunner.class)
@PrepareForTest({ FacesContext.class })
public class LoginFormTest {

现在继续使用 PowerMock 模拟 FacesContext,就像您对其他类所做的那样。唯一的区别是这次你在类而不是实例上执行replay()verify()

@Test
public void testLogout() {

    // mock all static methods of FacesContext
    PowerMock.mockStatic(FacesContext.class);

    FacesContext context = EasyMock.createMock(FacesContext.class);
    ExternalContext ext = EasyMock.createMock(ExternalContext.class);

    EasyMock.expect(FacesContext.getCurrentInstance()).andReturn(context);
    EasyMock.expect(context.getExternalContext()).andReturn(ext);

    ext.invalidateSession();
    // expect the call to the invalidateSession() method
    EasyMock.expectLastCall();
    context.release();

    // replay the class (not the instance)
    PowerMock.replay(FacesContext.class);
    EasyMock.replay(context);
    EasyMock.replay(ext);

    String userName = "testUserName";
    LoginForm loginForm = new LoginForm();
    loginForm.setUserName(userName);

    String expected = "/authentication/login.xhtml?faces-redirect=true";
    String actual = loginForm.logout();
    context.release();

    Assert.assertEquals(expected, actual);

    // verify the class (not the instance)
    PowerMock.verify(FacesContext.class);
    EasyMock.verify(context);
    EasyMock.verify(ext);
}

我创建了一个blog post,它更详细地解释了上述代码示例。

【讨论】:

    【解决方案2】:

    这个:

    FacesContext context = EasyMock.createMock(FacesContext.class);
    

    不改变返回值(在被测试的类中):

    FacesContext.getCurrentInstance()
    

    您需要扩展 FacesContext,然后使用您模拟的 FacesContext 调用受保护的方法 setCurrentInstance

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-12-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多