While reviewing my code coverage i noticed a lot of Unit tests fail to check finally blocks which try to close open InputStreams in finally blocks.
One Example excerpt is:
try {
f = new BufferedInputStream(new FileInputStream(source));
f.read(buffer);
} finally {
if (f != null)
try {
f.close();
} catch (IOException ignored) {
}
}
}
Is there any appropriate solution to check everything inside the finally block using JUnit4 ?
I know that a code coverage of 100% is not achievable while keeping maximum productivity in mind. However these red lines are sort of an eyecatcher in the report.
First of all consider using IOUtils.closeQuietly()
, which will reduce your untested code (and probably duplication) into:
try {
f = new BufferedInputStream(new FileInputStream(source));
f.read(buffer);
} finally {
IOUtils.closeQuietly(f);
}
Now it becomes hard. The "right" way would be to externalize the creation of BufferedInputStream
into another class and inject mock. Having a mock you can verify whether appropriate close()
method was invoked.
@JeffFoster's answer is pretty close to what I mean, however I would recommend composition over inheritance (at the expense of more code):
try {
f = fileSystem.open(source);
f.read(buffer);
} finally {
IOUtils.closeQuietly(f);
}
Where fileSystem
is an instance of FileSystem
interface with simple real implementation injected in production code or mock for testing.
interface FileSystem {
InputStream open(String file);
}
Another benefit of externalizing file opening is that if you one decide to remove buffering or add encryption, there is just a single place to modify.
Having that interface you instantiate your test code with mocks (using Mockito):
//given
FileSystem fileSystemMock = mock(FileSystem.class);
InputStream streamMock = mock(InputStream.class);
given(fileSystemMock.open("file.txt")).willReturn(streamMock);
//when
//your code
//then
verify(streamMock).close();