Search code examples
javajunitinitializationfieldjmockit

jUnit:NPE on private member initialization


Have jUnit test, which initializes my bean:

ShowProducts sp = new ShowProducts();

got NullPointerException on following line in ShowProducts.java:

    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);
    }

How to initialize properly this field in test?

EDIT:

faces-config:

<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>

Solution

  • Apparently your JSF FacesContext is not configured properly (I do no know much about faces, but I assume that setting them up and running in jUnit test is pretty complicated). However, there is help underway - use mocking.

    In your test case, you like to assure that: - ShowProducts retrieves proper locale out of faces context / view root - does other things properly.

    I recommend you to use jmockit. Your test case would become something like:

     @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
     }
    

    This techuique is applicable to lot of contextes and simplifies test code greatly.