Ive read so many articles on using Powermock and Mockito and tried so many different ways, but I still cant figure out the way to unit test the below static method.
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;
}
The code is part of a (legacy) class containing about 30 static methods like this and refactoring is not really an option. Similarly in some other static methods, DBconnections are being retrieved.
Eg : How do I mock the resource bundle ENTRIES_BUNDLE and unit test this method ?
I am looking for a pattern that could be applied generally to all the static methods.
Use ResourceBundle.getBundle( String, ResourceBundle.Control ) to get ResourceBundle to cache a bundle for the given String. You can subclass ResourceBundle.Control to provide any type of bundle your heart desires.
@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" );
}
Here's the subclassed Control:
ResourceBundle.Control myControl = new ResourceBundle.Control()
{
public ResourceBundle newBundle( String baseName, Locale locale, String format,
ClassLoader loader, boolean reload )
{
return myBundle;
}
};
And here's one way to mock the ResourceBundle (filling up the TreeMap with keys/values as needed for the unit tests left as an exercise for the reader):
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() );
}
};
You don't need to mock the ResourceBundle.getBundle
method. Simply create a ".properties" file at the proper place in the test source tree, instead. This will still be a perfectly good and useful unit test.
We had a simular issue mocking the ResourceBundle.getString() method.
java.util.MissingResourceException: Can't find resource for bundle $java.util.ResourceBundle$$EnhancerByMockitoWithCGLIB$$e9ea44f0, key name
Our problem was that the method was final, which makes it impossible for mockito to mock the method.
Instead we used this soultion: https://code.google.com/p/powermock/wiki/MockSystem
Note that @PrepareForTest({ClassThatCallsTheSystemClass.class}) is NOT the ResourceBundle class!
If you are using the following libraries: mockito-all and jmockit do this steps:
Let say that you want to mock the method yyyy from the xxxx.class
@MockClass(realClass = xxxx.class)
public static class MyClass {
@Mock
public static void yyyy(){
......
}
}
in your test:
@Test
public void test() {
Mockit.setUpMock(MyClass.class);
}