我有Runnable
行:
public void run() {
InputStream inputStream = null;
try {
inputStream = new FileInputStream(file);
//more stuff here
}
catch (Exception e) {
//simplified for reading
}
finally {
if(inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {}
}
}
}
如何测试inputStream.close()
被调用?我目前正在使用Mockito和JUnit。我知道注入inputStream
是一个想法,但我不希望在调用run?()
之前使用资源,因此它是一个局部变量。那么如何以允许我测试close是否被调用的方式重新设计我的代码呢?
答案 0 :(得分:15)
如果我理解正确的任务,可能就像这样
static boolean isClosed;
public void run() {
InputStream inputStream = null;
try {
inputStream = new FileInputStream(file) {
@Override
public void close() throws IOException {
isClosed = true;
super.close();
}
};
// more stuff here
答案 1 :(得分:6)
由于没有理由将InputStream暴露在此方法范围之外,因此存在测试问题。
但我认为你并不直接关心被关闭的InputStream
。你想测试一下,因为你被告知这是一个很好的做法(而且确实如此)。但我认为你真正关心的是流被打开的负面影响。有什么影响?
尝试修改此方法,使其不关闭流,然后多次执行。你有内存泄漏,或文件句柄或其他一些tomfoolery?如果是这样,你就有了合理的考验。
或者,继续展示一个装饰好的InputStream,它可以告诉你它是否已经关闭。使其受到保护。这是“不纯”,但务实的做法。
答案 2 :(得分:5)
要检查是否调用了close()方法,可以使用Mockito.spy()创建一个可以记忆调用的代理对象。 Spy委托对底层InputStream的所有调用,只记住发生的事情:
InputStream inputStreamSpy = Mockito.spy(inputStream);
// a code that is expected to close your stream goes here ...
Mockito.verify(inputStreamSpy).close();
这实际上并不能解决注入InputStream实例的问题。看起来你需要某种工厂,可以为你打开一个流,你可以在单元测试中模拟那个工厂。我们将这个工厂称为FileSystem:
public class FileSystem {
public FileInputStream newFileInputStream(File file) {
return new FileInputStream(file);
}
}
现在,您可以注入FileSystem的一个实例,并且在执行run方法之前它不会使用资源:
public void run() {
InputStream inputStream = null;
try {
inputStream = fileSystem.newFileInputStream(file);
//more stuff here
}
catch (Exception e) {
//simplified for reading
}
finally {
if(inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {}
}
}
}
@Test
public void runShouldCloseInputStream() {
InputStream inputStream = ...
InputStream inputStreamSpy = Mockito.spy(inputStream);
FileSystem fileSystemMock = Mockito.mock(FileSystem.class);
when(mockFileSystem.newFileInputStream(Mockito.any(File.class)))
.thenReturn(inputStreamSpy);
MyRunnable instance = new MyRunnable(mockFileSystem);
instance.run();
verify(inputStreamSpy).close();
}
间谍可以做更多的事情然后只是倾听,你可以教它改变行为使用Mockito.when(),就像你使用常规模拟一样。
答案 3 :(得分:1)
你可以这样做......
try
{
inputStream.readLine();
}
catch (IOException e)
{
Assert.assertEquals(e.getLocalizedMessage(), "Stream closed");
}
答案 4 :(得分:0)
您可以在测试中写下:
try {
run();
} catch (IOException e) {
Assert.fail();
}
当您的方法关闭strem并发生异常时,测试将失败。
答案 5 :(得分:0)
用于测试URL流的Kotlin实现已关闭
//close the connection
streamURL.close()
//stream should not be available if it is closed
try { streamURL.available() }
//java.net.URL provides simple "closed" message on IO URL
catch (ex: IOException) { Assert.assertEquals("closed", ex.message) }