2014-01-21 154 views
0

我試圖單元測試,做嘲諷Locale.forLanguageTag

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

爲了測試,我需要模擬java.util.Locale的方法。我使用PowerMock和的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); 
    } 
} 

但似乎嘲笑的方法從mockLocale調用從來不被稱爲;相反,我從java.util.Locale.getISO3Language(我想模擬)得到java.util.MissingResourceException。如何解決這個問題?

回答

2

一種方法(忽略當前錯誤的原因)是將Locale對象包裝在可以正確模擬的外觀中。然後可以將此對象作爲字段/構造函數參數傳遞到您的類中。

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

然後在你的測試用例,你可以在構造你的Context對象之前嘲笑一個LocalResolver

我總是比較喜歡這種方法,而不是試圖模擬具體的類。它通常具有超出測試便利的優點。

+0

我的案例的解決方案是[模擬系統類獲取系統屬性](http://stackoverflow.com/a/20408354) –