First of all, consider using IOUtils.closeQuietly()
, which will reduce your unverified code (and probably duplication) by:
try { f = new BufferedInputStream(new FileInputStream(source)); f.read(buffer); } finally { IOUtils.closeQuietly(f); }
Now it’s getting hard. The “right” way is to externalize the creation of the BufferedInputStream
in another class and introduce the layout. With the layout, you can check if the appropriate close()
method was involved.
@JeffFoster's answer is pretty close to what I mean, however I would recommend composition over inheritance (due to more code):
try { f = fileSystem.open(source); f.read(buffer); } finally { IOUtils.closeQuietly(f); }
Where fileSystem
is an instance of the fileSystem
interface with a simple real implementation introduced into production code or layout for testing.
interface FileSystem { InputStream open(String file); }
Another advantage of external file disclosure is that if you decide to remove buffering or add encryption, there is only one place to change.
Using this interface, you create test code using 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();
Tomasz Nurkiewicz
source share