0

I'm trying to unit test a method that does

public static Context fromLanguageTag(final String languageTag) {
    final Context context = new Context();
    final Locale locale = Locale.forLanguageTag(languageTag);
    context.language = locale.getLanguage().length()==3 ? locale.getLanguage() : locale.getISO3Language();
    return context;
}

To test that I need to mock java.util.Locale. I'm using PowerMock and Mockito:

@RunWith(PowerMockRunner.class)
@PrepareForTest({ Locale.class })
public class ContextTest {  
    public void testFromLanguageTag() throws Exception {
       mockStatic(Locale.class);
       final Locale mockLocale = mock(Locale.class);
       when(mockLocale.getLanguage()).thenReturn(LANGUAGE_3_OUTPUT);
       when(mockLocale.getISO3Language()).thenReturn(LANGUAGE_ISO);
       when(Locale.forLanguageTag(Mockito.eq(LANGUAGE_TAG_LONG_INPUT))).thenReturn(mockLocale);
       final Context c = Context.fromLanguageTag(LANGUAGE_TAG_LONG_INPUT);
       assertThat(c.getLanguage()).isEqualTo(LANGUAGE_3_OUTPUT);
   }
}

But it seems the mocked method calls from mockLocale are never called; instead I get a java.util.MissingResourceException from java.util.Locale.getISO3Language (which I want to mock). How can fix that?

Martin Schröder
  • 4,176
  • 7
  • 47
  • 81

1 Answers1

2

One approach (which ignores the cause of your current error), is to wrap the Locale object in a façade that you can mock properly. This object can then be passed in as a field/constructor-param into your class.

E.g.

public interface LocaleResolver {    
  // add signatures for the methods you care about in Locale (only)
}

public class PlatformLocaleResolver implements LocaleResolver {
  // delegate all methods to the corresponding `Locale` methods
}

public class Context {
  // take LocaleResolver in constructor
  // (or, if preferred, expose a setter to adjust a class field)
}

Then in your test case, you can mock a LocalResolver before you construct your Context object.

I always prefer an approach such as this, instead of trying to mock concrete classes. It often has benefits that extend beyond ease of testing.

Duncan Jones
  • 67,400
  • 29
  • 193
  • 254