We have a URL object in one of our Java classes that we want to mock, but it's a final class so we cannot. We do not want to go a level above, and mock the InputStream because that will still leave us with untested code (we have draconian test coverage standards).
I've tried jMockIt's reflective powers but we work on Macs and there are problems with the Java agent handler that I haven't been able to resolve.
So are there any solutions that do not involve using real URLs in the junit test?
I would look again at why you want to mock a final data object. Since by definition you aren't subclassing the object in your actual code, and it's not going to be the object under test, you shouldn't need to white-box test this code; just pass in whatever (real) URL objects are appropriate, and check the output.
Mock objects are useful when it's difficult to create a real object appropriate, or the real object's method are either time-consuming or depend on some stateful external resource (like a database). Neither of these apply in this case so I can't see why you can't just construct a real URL object representing the appropriate resource location.
JMockit does indeed allow you to mock a final JRE class like java.net.URL.
It seems the Attach API in jdkDir/lib/tools.jar available in implementations of JDK 1.6 other than Sun's does not work as well. I guess this stuff is still too new/advanced, or simply didn't get the necessary attention from the other JDK vendors (Apple, IBM with the J9 JDK, Oracle with the JRockit JDK).
So, if you run into problems by having tools.jar in the classpath, try using the "-javaagent:jmockit.jar" JVM argument. It tells the JVM to directly load the java agent at startup, without using the Attach API. That should work in the Apple JDK 1.5/1.6.
Like Rob said, if what you want is to mock the connection returned from the URL, you can extend
URLStreamHandler
. For instance, with mockito:I think you can use Powermock to do this. I was able to mock URL class using PowerMock lately. Hope this helps.
/* Actual class */
/* Test class */
When I have a class that can't be easily mocked because it is final (or sealed in C#), my usual route is to write a wrapper around the class and use the wrapper wherever I would use the actual class. Then I would mock out the wrapper class as necessary.
I went with the following:
This gives me a real URL object that contains my mock data.