4

编辑:清理了可读性的问题。请忽略截至 10 月 31 日的评论。

在我们的应用程序堆栈中,我们使用许多较小的 jar 模块,这些模块组合成最终的 Web 应用程序。一个模块定义了 JSF 特性,比如实现这个ViewScope。

现在除了集成测试,我们希望能够对每个部分进行单元测试,因此需要一种方法来模拟完整的 Faces 上下文(通过包装器访问)来测试使用它的类。

这里重要的部分是完整的,这意味着它必须初始化ViewMap,因为这是我们ViewScope放置对象的地方。


我尝试了不同的方法:

1)页岩测试:我在这方面做得最远,但不幸的是该项目已经退役。

到目前为止,我已经将 FacesContext 包装在一个 Provider 中,它允许我用 Mocked FacesContext 替换它以进行测试。我还修改了 AbstractViewControllerTestCase 的页岩实现以包含应用程序上下文。

但是,当调用MockedFacesContext.getViewRoot().getViewMap()this 时会抛出一个UnsupportedOperationException. 原因似乎是 MockApplication 没有实例化此方法调用所需的 Application.defaultApplication (它为空)。这似乎是页岩测试的限制。


2) JMock或 mockito在我看来,这些似乎并没有真正嘲笑任何东西,因为大多数成员将保持为空。不知道 JMock 或 mockito 是否真的可以调用propper初始化方法。


3) Custom Faces Mocker:对我来说,这似乎是唯一剩下的选择,但我们真的没有时间分析 Faces 是如何初始化的并重新创建用于模拟目的的行为。也许有人以前没有这个并且可以分享主要的航点和陷阱?


或者有没有其他方法可以在 Web 应用程序之外模拟 FacesContext?

4

1 回答 1

4

我会选择PowerMock +Mockito:

从您的链接:

private Map<String,Object> getViewMap() {
    return FacesContext.getCurrentInstance().getViewRoot().getViewMap();
}

在测试中:

@RunWith(PowerMockRunner.class)
@PrepareForTest({ FacesContext.class });
public class TheTest {
    /*
     * fake viewMap.
     */
    private Map<String,Object> viewMap = Maps.newHashMap() // guava

    /**
     * mock for FaceContext
     */
    @Mock
    private FacesContext faceContext;

    /**
     * mock for UIViewRoot
     */
    @Mock
    private UIViewRoot uiViewRoot;

    @Before
    public void setUp() {
        Mockito.doReturn(this.uiViewRoot).when(this.faceContext).getViewRoot();
        Mockito.doReturn(this.viewMap).when(this.uiViewRoot).getViewMap();

        PowerMock.mockStatic(FacesContext.class);
        PowerMock.doReturn(this.faceContext).when(FacesContext.class, "getCurrentInstance");
    }

    @Test
    public void someTest() {
        /*
         * do your thing and when  
         * FacesContext.getCurrentInstance().getViewRoot().getViewMap(); 
         * is called, this.viewMap is returned.
         */
    }
}

一些阅读:

于 2011-11-30T07:18:40.783 回答