July 29, 2004
Mocking a URL

Tulna's having a bit of trouble with some unit testing at the moment. The lovely Emma has pointed out a few holes in our test coverage, and Tulna is endeavouring to fill them.

She's currently working on building tests for our configuration classes. We use Digester to pull in all our configuration from XML. In real life, it's all as sweet as a nut, but obviously we still want unit tests to ensure that any future breakage is discovered PDQ.

We run digester in a ServletContextListener's contextInitialized(). After setting up our digester, after all that addObjectCreate(), addBeanPropertySetter() shenanigans, the code which actually does the digesting looks like this:

URL configFileURL = context.getResource("/WEB-INF/config.xml");
InputStream configFileStream = configFileURL.openStream();
config = (Config) digester.parse(configFileStream);

Question is, how do we get our test data into configFileStream? The context object is a mock, so we can do anything we like there - but how do we mock URL? It's a final class, so we can't sub-class it...

Posted to Java by Simon Brunning at July 29, 2004 05:12 PM
Comments

Modify your class to accept a stream instead of hardcoding where the data comes from.

Posted by: Bob Lee on July 29, 2004 07:24 PM

There is no need to mock the URL really. The only reason you want to mock something is if you need to define expectations on how the code you are testing will use it (for example "I need to make sure object A calls method Z with these arguments"). Your Mock context can return a normal URL object - it just happens to be pointing to a fake/test URL. Then you assert that your URL gets retrieved from the Mock context.

If all you want is a dumb/fake object, then just instantiate one (if it's a value-object type thing like URL) or create a stub.

Posted by: Sam Newman on July 29, 2004 10:18 PM

If you really want to mock the stream, you could use aspects to achieve this. Make an aspect that either returns your own subclass of URL, or that returns a ByteArrayInputStream that is prefilled with the data you need.

Posted by: Alex on July 30, 2004 08:24 AM

well...almost, since URL is final, that won't work, so stick with the ByteArrayInputStream aproach

Posted by: Alex on July 30, 2004 08:33 AM

Its horrible that sun does this kind of stuff - sure make it final but always provide an interface if you are going to do this!

For URL its useful to just wrap it into something you would like to use - like WebURL then you can mock it and at the same time give it nicer behavior.

Others have given you alternatives - but I quike like the conveniance of URL over byte streams - so a WebUrl gives you a handy way of setting up a test one with the contents of a String - ideal for testing and nice and clear.

Tim

Posted by: Tim on August 2, 2004 08:47 AM

Try implementing a URLStreamHandler with your very own testing URL scheme. I know there's a framework out there that does this (we use a modified version of this) but can't find it on Google right now...

Posted by: Phil on February 11, 2005 09:34 PM
Post a comment
Name:


Email Address:


URL:



Comments:


Remember info?