Question

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>
Was it helpful?

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.

OTHER TIPS

Accessing static methods makes writing tests hard.

Either pass the Locale with the constructor or use a setter.

The easiest change would be to add a second constructor with a Locale as parameter and use it for the unittest. The default constructor then initializes the field from the FacesContext.

Towards a cleaner design you should extract a Localizer where you handle all the localization, so to separate then ShowProducts which doesn't need the FacesContext from the Localizer which does.

The Localizer would be something like:

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

This has nothing to do with ShowProducts. Not sure what you need getLanguge() for.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top