«« iBook Woes Unit Test Eclipse View »»
blog header image
Java IOException and Code Coverage

Code coverage is pretty cool -- it lets you see how much of your code your unit tests exercise. The only problem is that there are a few strange cases which are hard or impossible to cover.

An impossible coverage example is a private constructor with no accessor method. Library classes like java.lang.Math have private constructors because all of the methods are static. It doesn't make sense to have an object of this class so there's no way to get to the constructor for a good reason. Unfortunately coverage tools like jcoverage count the empty constructor as a missed line of coverage.

Why do we care about one silly line? Well because from a project management perspective it's a lot better to say "we need to keep 100% code coverage" than it is to say "we need to stay as close to 100% as we can but we accept it's not possible because there are these weird cases...". Always being 100% is a hard and fast, easy to enforce rule -- if the developers are allowed to be less than 100% you'll never be able to keep track of all of the special cases the team had to work around. So covering all of the code is a good thing.

So that brings me to my particular example -- the IOException. They are checked exceptions and you have to catch them at some point in your code. When you do, you'll have to cover those catch statements or you'll be less than 100% for code coverage. Throwing an IOException is not an easy thing to do (besides FileNotFoundException**) with regular files because it usually involves some sort of catastrophic I/O error, hence the name.

My buddy Andrew reminded me of a great way to induce IOExceptions though: create a new class that subclasses the File class and override some of the read/write operations as necessary so that it always throws an IOException. Bingo, every time you use that dummy file you'll get the exception and cover your code. It's not a real file but it's the closest you can get. After all, you are testing your code and how it handles exceptions, not the File class.

Actually, that isn't quite my example -- it involves a bit more. Our fourth year project's Java code is layered, and API calls are made down the layers. Most of the file-related calls look like this:

public void upperAPIMethod(String filename)
{
   try
   {
      lowerAPI.setFile(filename);
   }
   catch (IOException ioe)
   {
      throw ApplicationException("Error reading the file!");
   }
}

The user interface is above this method in the layering, so I want to throw my own special exception ApplicationException up to it. I don't want my UI dealing with IOExceptions (and others) -- just one type of exception that it can take the message out of and display in a modal dialog box.

This method takes a string as input, has no output and throws an ApplicationException. Herein lies the problem: there is no string that will generate that ApplicationException! For black box unit testing, this is a very bad thing. So how could I change my method?

public void upperAPIMethod(File fileToSet)
{
   try
   {
      lowerAPI.setFile(fileToSet);
   }
   catch (IOException ioe)
   {
      throw ApplicationException("Error reading the file!");
   }
}

Now I can pass my dummy file in and get the ApplicationException out. Great. The only bad part is that each layer (including the UI) needs to know about File objects instead of regular String objects. Is this really a bad thing?

**I'm not concerned about FileNotFoundExceptions in this discussion because I catch them before IOException and throw an exception with a different error message -- "file not found" instead of "error reading file"

Posted at October 29, 2003 at 11:19 PM EST
Last updated October 29, 2003 at 11:19 PM EST
Comments


Very insightful.

I'd probably go with the coupling of a File over a string. I am guessing your concern is that you may want to move beyond just files (aka urls / uris) and your upper api methods wouldn't need to change? Maybe? Anywho, that's what refactoring is all about.

Do you know of free .net code coverage tools?

» Posted by: andrew at October 30, 2003 09:49 AM

Not really ... that is the problem with the .NET world: you have to pay for almost everything.

» Posted by: Ryan at October 30, 2003 10:29 AM

Good idea with for creating the IOExceptions andrew...

» Posted by: kris at November 4, 2003 10:40 AM

Great comments guys. Peter FDA

» Posted by: Peter at November 11, 2003 02:28 AM

Check out http://workspaces.gotdotnet.com/ncover for a free .net code coverage analysis tool.

» Posted by: Peter Waldschmidt at January 18, 2004 09:01 PM
Google
 
Search scope: Web ryanlowe.ca