views:

325

answers:

3

I'm writing some Java code that uses a FileReader to load data from a few input files. I'm using TDD pretty heavily, and I'd like to add some tests that ensure that I'm cleaning up properly by calling close() on the reader when I'm done with it. Unfortunately, I can't come up with a good way to test for this. Anyone have any insights?

Edited to add: I know I can test explicitly for the close call using mock objects, but I'd like to avoid it if possible, partly because I find they lead to somewhat brittler code, and partly because I'm curious whether it's possible to write code that can recognize the effects of not closing a file.)

+1  A: 

If you can pass the FileReader object in to the call then you can provide a custom FileReader that has an overridden close method -- in that, you have a boolean variable that checks on closed or not. You can then use that for your unit test.

javamonkey79
+3  A: 

I think the way to do this is to inject the FileReader, or a Factory that creates the FileReader, into your class. Then in your unit test you can inject a mock version of the FileReader and check that the proper method on it has been called. You might want to look at JMock to create the mock FileReader and set up the expectation for the close method call.

tvanfosson
I'm actually wondering if there's a way to do it without mocking, but I still upvoted this for being generally good advice.
Moss Collum
I'd say that dependency injection has value beyond just enabling mock and would be worth doing anyway, although I'd probably inject the interface -- InputStreamReader? DataReader? -- instead of a FileReader in order to reduce the coupling even more. Once you have DI, mocking is a natural step.
tvanfosson
+2  A: 

One way that should work is to test the ready() method after you close your FileReader which should throw an exception. For example:

FileReader fr = new FileReader("somefile");
// ... file reader activity
fr.close();

// After closing the reader, the ready() method should cause an IOException:
boolean isOpen = true;
try {
  isOpen = fr.ready();
} catch (IOException e) {
  isOpen = false;
}
assertFalse("FileReader is still open", isOpen);
Chris B.