我读了很多关于使用Powermock和Mockito的文章并尝试了很多不同的方法,但我仍然无法找到对下面的静态方法进行单元测试的方法。
public static Map<String, String> getEntries() {
Map<String, String> myEntriesMap = new TreeMap<String, String>();
ResourceBundle myEntries = ResourceBundle.getBundle(ENTRIES_BUNDLE);
Enumeration<String> 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并对此方法进行单元测试? 我正在寻找一种通常适用于所有静态方法的模式。
答案 0 :(得分:8)
使用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,作为读者练习的单元测试需要):
ResourceBundle myBundle = new ResourceBundle()
{
protected void setParent( ResourceBundle parent )
{
// overwritten to do nothing, otherwise ResourceBundle.getBundle(String)
// gets into an infinite loop!
}
TreeMap<String, String> tm = new TreeMap<String, String>();
@Override
protected Object handleGetObject( String key )
{
return tm.get( key );
}
@Override
public Enumeration<String> getKeys()
{
return Collections.enumeration( tm.keySet() );
}
};
答案 1 :(得分:4)
您无需模拟ResourceBundle.getBundle
方法。只需在测试源树中的适当位置创建“.properties”文件即可。这仍然是一个非常好的和有用的单元测试。
答案 2 :(得分:1)
我们有一个模拟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类!
答案 3 :(得分:0)
如果您使用以下库: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);
}