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