jUnit:私有成员初始化的NPE

时间:2011-12-01 15:17:29

标签: java junit initialization field jmockit

进行jUnit测试,初始化我的bean:

ShowProducts sp = new ShowProducts();

在ShowProducts.java中的以下行获得NullPointerException

    private Locale locale = FacesContext.getCurrentInstance().getViewRoot()
                .getLocale();

...
    public Locale getLocale() {
        return locale;
    }

    public String getLanguage() {
        return locale.getLanguage();
    }

    public void localize() {
        String localeParam = FacesContext.getCurrentInstance()
                .getExternalContext().getRequestParameterMap().get("lang");
        locale = new Locale(localeParam);
        FacesContext.getCurrentInstance().getViewRoot().setLocale(locale);
    }

如何在测试中正确初始化此字段?

修改

面-配置:

<application>
    <locale-config>
        <default-locale>ru</default-locale>
        <supported-locale>ua</supported-locale>
    </locale-config>
    <resource-bundle>
        <base-name>msg</base-name>
        <var>m</var>
    </resource-bundle>
</application>

.xhtml:

    <h:form>
        <h:commandLink action="#{showProducts.localize}" includeViewParams="true"
                       rendered="#{showProducts.language=='ua'}">
            #{m.rus}.
            <f:param name="lang" value="ru"/>
        </h:commandLink>
        <h:commandLink action="#{showProducts.localize}" includeViewParams="true"
                       rendered="#{showProducts.language=='ru'}">
            #{m.ukr}.
            <f:param name="lang" value="ua"/>
        </h:commandLink>
    </h:form>

2 个答案:

答案 0 :(得分:3)

显然你的JSF FacesContext没有正确配置(我对面孔知之甚少,但我认为在jUnit测试中设置和运行它们非常复杂)。但是,正在进行帮助 - 使用模拟。

在您的测试用例中,您希望确保:     - ShowProducts从faces context / view root中检索正确的语言环境     - 做其他事情。

我建议你使用jmockit。您的测试用例将变为:

 @Test
 public void testShowProducts(@Cascading final FacesContext facesContext) {
        final Locale locale = new Locale(...)
        new Expectations() {
           {
              FacesContext.FacesContext.getCurrentInstance().getViewRoot().getLocale();
              returns(locale);
           }


        };
       ShowProducts sp = new ShowProducts();

       ...  do your assertions other stuff there
 }

该技术适用于许多环境并大大简化了测试代码。

答案 1 :(得分:1)

访问静态方法会使编写测试变得困难。

使用构造函数传递Locale或使用setter。

最简单的更改是添加第二个构造函数,并将Locale作为参数,并将其用于unittest。然后,默认构造函数从FacesContext初始化字段。

为了更清洁的设计,您应该提取Localizer处理所有本地化的位置,然后将ShowProductsFacesContext中分离出来Localizer这样做。

Localizer类似于:

public class Localizer {
    public void localize() {
        String localeParam = FacesContext.getCurrentInstance()
                .getExternalContext().getRequestParameterMap().get("lang");
        locale = new Locale(localeParam);
        FacesContext.getCurrentInstance().getViewRoot().setLocale(locale);
    }
}

这与ShowProducts无关。不确定您需要getLanguge()