PowerMock is a very handy extension to the Mockito mocking framework. It extends Mockito by allowing the mocking of static methods and final classes. Obviously to do this some interesting mangling is going on inside the JVM. Occasionally it is possible to run into some very confusing error messages.
Yesterday my colleague [Candle] and I spent a very vexing half hour over this puzzle before we figured out the answer. So I though I would share it to see how long it takes others to figure it out. ^^
Consider the following class. Do not worry that it basically does nothing. This is just the minimum to show the puzzle.
import java.net.URL;
import com.google.common.cache.CacheLoader;
public class Loader extends CacheLoader<URL, String> {
@Override
public String load (URL u) throws Exception {
u.openConnection();
return null;
}
}
And then consider this test class.
import java.net.URL;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
@RunWith(PowerMockRunner.class)
@PrepareForTest({ URL.class })
public class LoaderTest {
@Test
public void test () throws Exception {
URL url = PowerMockito.mock(URL.class);
Loader loader = new Loader();
loader.load(url);
}
}
When run this test will fail with the following exception. I have edited it slightly to match the cuttings above. It throws in Loader.load() at the call to u.openConnection().
java.lang.AbstractMethodError: java/net/URLStreamHandler.openConnection(Ljava/net/URL;)Ljava/net/URLConnection;
at java.net.URL.openConnection(URL.java:957)
at Loader.load(Loader.java:7)
Now try and figure out what is going on here. Go go go! And for bonus points, suggest a solution that will fix it enough to make the test pass.