unit testing使用资源包的静态方法

我已经阅读了很多关于使用Powermock和Mockito的文章,并尝试了很多不同的方法,但我仍然无法找到unit testing以下静态方法的方法。

public static Map getEntries() { Map myEntriesMap = new TreeMap(); ResourceBundle myEntries = ResourceBundle.getBundle(ENTRIES_BUNDLE); Enumeration enumList = myEntries.getKeys(); String key = null; String value = null; while (enumList.hasMoreElements()) { key = enumList.nextElement().toString(); value = myEntries.getString(key); myEntriesMap.put(key, value); } return myEntriesMap; } 

代码是包含大约30个这样的静态方法的(遗留)类的一部分,并且重构实际上不是一个选项。 类似地,在一些其他静态方法中,正在检索DB连接。

例如:如何模拟资源包ENTRIES_BUNDLE并对此方法进行unit testing? 我正在寻找一种可以普遍适用于所有静态方法的模式。

使用ResourceBundle.getBundle(String,ResourceBundle.Control)获取ResourceBundle以缓存给定String的包。 您可以将ResourceBundle.Control子类化,以提供您心中所需的任何类型的包。

 @Test public void myTest() { // In your Test's init phase run an initial "getBundle()" call // with your control. This will cause ResourceBundle to cache the result. ResourceBundle rb1 = ResourceBundle.getBundle( "blah", myControl ); // And now calls without the supplied Control will still return // your mocked bundle. Yay! ResourceBundle rb2 = ResourceBundle.getBundle( "blah" ); } 

这是子类控件:

 ResourceBundle.Control myControl = new ResourceBundle.Control() { public ResourceBundle newBundle( String baseName, Locale locale, String format, ClassLoader loader, boolean reload ) { return myBundle; } }; 

这里有一种模拟ResourceBundle的方法(使用键/值填充TreeMap,作为读者练习的unit testing需要):

 ResourceBundle myBundle = new ResourceBundle() { protected void setParent( ResourceBundle parent ) { // overwritten to do nothing, otherwise ResourceBundle.getBundle(String) // gets into an infinite loop! } TreeMap tm = new TreeMap(); @Override protected Object handleGetObject( String key ) { return tm.get( key ); } @Override public Enumeration getKeys() { return Collections.enumeration( tm.keySet() ); } }; 

您不需要模拟ResourceBundle.getBundle方法。 只需在测试源树中的适当位置创建“.properties”文件即可。 这仍然是一个非常好的和有用的unit testing。

我们有一个模拟ResourceBundle.getString()方法的类似问题。

java.util.MissingResourceException: Can't find resource for bundle $java.util.ResourceBundle$$EnhancerByMockitoWithCGLIB$$e9ea44f0, key name

我们的问题是该方法是最终的,这使得mockito无法模拟该方法。

相反,我们使用了这个灵魂: https : //code.google.com/p/powermock/wiki/MockSystem

请注意,@ PrepareForTest({ClassThatCallsTheSystemClass.class})不是ResourceBundle类!

如果您使用以下库:mockito-all和jmockit执行以下步骤:

假设您要从xxxx.class中模拟yyyy方法

 @MockClass(realClass = xxxx.class) public static class MyClass { @Mock public static void yyyy(){ ...... } } 

在你的测试中:

 @Test public void test() { Mockit.setUpMock(MyClass.class); }