编辑:清理了问题的可读性。请忽略截至 10 月 31 日的评论。
在我们的应用程序堆栈中,我们使用许多较小的 jar 模块,这些模块组合成最终的 Web 应用程序。一个模块定义了 JSF 特性,比如实现 this视野范围。
现在除了集成测试,我们希望能够对每个部分进行单元测试,因此需要一种方法来模拟完整的 Faces 上下文(通过包装器访问)来测试使用它的类。
这里重要的部分是完整意味着它必须有一个初始化的 ViewMap
因为这是我们的ViewScope
把它的对象。
我尝试了不同的方法:
1) 页岩测试 :我在这方面走得最远,但不幸的是该项目已退役。
到目前为止,我已经将 FacesContext 包装在一个 Provider 中,它允许我用 Mocked FacesContext 替换它以进行测试。我还修改了 AbstractViewControllerTestCase 的页岩实现以包含应用程序上下文。
然而,当调用 MockedFacesContext.getViewRoot().getViewMap()
因为这会抛出 UnsupportedOperationException
.原因似乎是 MockApplication 没有实例化此方法调用所需的 Application.defaultApplication (它为空)。这似乎是页岩测试的限制。
2) JMock或模拟在我看来,这些似乎并没有真正 mock 任何东西,因为大多数成员将保持为空。不知道 JMock 或 mockito 是否真的可以调用propper初始化方法。
3) 自定义面孔模拟器:对我来说,这似乎是唯一剩下的选择,但我们真的没有时间分析 Faces 是如何初始化的并重新创建用于模拟目的的行为。也许有人以前没有这个并且可以分享主要的航点和陷阱?
或者有没有其他方法可以在 Web 应用程序之外模拟 FacesContext?
最佳答案
我会选择 PowerMock +模拟:
从您的链接:
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.
*/
}
}
一些阅读:
关于jsf - 如何在实际 Web 应用程序之外使用 ViewMap 模拟 JSF FacesContext 以进行单元测试?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7334868/