JMockit创建一个假的FacesContext ResourceBundle

时间:2016-06-27 08:25:42

标签: java jsf mocking jmockit

以前我一直在@Mocked上使用ResourceBundle,例如

@Test
public void testMyMethod(@Mocked final ResourceBundle resourceBundle) {
    new Expectations() {
        {
            resourceBundle.getString("someString");
            result = "myResult";
        }
    }
}

这一直很好,直到我正在测试的特定方法具有以下代码行

DateFormat format = new SimpleDateFormat("yyyy-MM-dd");

如果我使用上面的方法创建了一个模拟ResourceBundle,那么我的测试会在这一行上抛出一个NumberFormatException,原因是SimpleDateFormat构造函数可以使用ResourceBundle同时为其默认Calendar构建Locale实例。

所以我想要做的是创建一个假的,它会返回我对getString的一些调用的模拟结果,以及其他的默认值。

new Mockup<ResourceBundle>() {
    @Mock
    public String getString(Invocation inv, String key) {
        if ("someString".equals(key)) {
            return "myResult";
        } else if ("someOtherString".equals(key)) {
            return "myOtherResult";
        } else {
            return inv.proceed();
        }
    }
};

我希望在通过ResourceBundle检索时使用此假FacesContext,例如

FacesContext facesContext = FacesContext.getCurrentInstance();
ResourceBundle bundle = facesContext.getApplication().getResourceBundle(facesContext, "myBundle");

由于我的测试没有在正在运行的容器中运行,我正在嘲笑FacesContext并且我想使用我创建的假货,所以我有类似的东西

@Test
public void testMyMethod(@Mocked final FacesContext facesContext) {
    final ResourceBundle resourceBundle = new Mockup<ResourceBundle>() {
        @Mock
        public String getString(Invocation inv, String key) {
            if ("someString".equals(key)) {
                return "myResult";
            } else if ("someOtherString".equals(key)) {
                return "myOtherResult";
            } else {
                return inv.proceed();
            }
        }
    }.getMockInstance();

    new Expectations() {
    {
        facesContext.getApplication().getResourceBundle(facesContext, "myBundle");
        result = resourceBundle; 
    }

    unitUnderTest.methodUnderTest();
}

然而,对于所有情况,它看起来都使用默认的ResourceBundle getString()而不是使用我的假货

1 个答案:

答案 0 :(得分:0)

好的,所以我设法找到了一个可以满足我想要的解决方案,让这项工作的关键是在Deencapsulation.invoke上使用FacesContext.setCurrentInstance()

@Test
public void testMyMethod() {
    final FacesContext facesContext = new Mockup<FacesContext>() {
        @Mock
        public Application getApplication() {
            return new MockUp<Application>() {
                @Mock
                public ResourceBundle getResourceBundle(FacesContext ctx, String name) {
                    return new MockUp<ResourceBundle>() {
                        @Mock
                        public String getString(Invocation inv, String key) {
                            if ("someString".equals(key)) {
                                return "myResult";
                            } else if ("someOtherString".equals(key)) {
                                return "myOtherResult";
                            } else {
                                return inv.proceed();
                            }
                        }    
                    }.getMockInstance();
                }
            }.getMockInstance();
        }
    }.getMockInstance();

    Deencapsulation.invoke(FacesContext.class, "setCurrentInstance", facesContext);

    unitUnderTest.methodUnderTest();
}