为什么Mockito在使用InputStreams时表现得很奇怪



在调试时,我在使用Mockito 1.10时遇到了一些非常奇怪的事情。我希望有人能解释这里的行为:

当我运行以下程序时,我的线程挂起,我的测试永远不会返回。创建的Java进程的CPU也是天文数字!

@Test(expected = IOException.class)
public void mockitoWeirdness() throws IOException {
    final InputStream mis = mock(InputStream.class);
    doThrow(IOException.class).when(mis).read();
    ByteStreams.copy(mis, new ByteArrayOutputStream());
}

当我按照如下方式手动存根此方法时,会抛出预期的IOException:

@Test(expected = IOException.class)
public void nonMockitoExpected() throws IOException {
    final InputStream mis = new InputStream() {
        @Override
        public int read() throws IOException {
            throw new IOException();
        }
    };
    ByteStreams.copy(mis, new ByteArrayOutputStream());
}

了解mockito方法是如何失败的以及为什么失败的任何帮助都将是非常棒的。

如果您查看ByteStreams的实现,您可以看到使用了read(buf)方法。在您的情况下,它返回null,因为它没有mock定义,这会导致copy方法中出现无休止的循环。

您可以更改默认的mock行为,也可以手动添加read(buff)方法的定义。

您需要设置mock来调用InputStream的实际方法,而此时您还没有将它们清除为

final InputStream mis = Mockito.mock(InputStream.class, Mockito.CALLS_REAL_METHODS);

javadoc声明

当使用遗留代码时,此实现可能会有所帮助。什么时候如果使用此实现,未构建的方法将委托给真正的实施。这是一种创建部分mock对象的方法默认情况下调用真实方法

默认情况下,Mockito会嘲笑一切。您首先使用的ByteStreams#copy方法调用InputStream#read(byte[])。由于mockito已经对其进行了嘲讽,它将返回0,ByteStreams#copy将其解释为"从该流中有更多内容要读取",并继续读取(无限循环)。

通过使用Mockito.CALLS_REAL_METHODS,您告诉Mockito调用InputStream中的实际实现,它将委托给read(),您已将其截断以引发异常。

相关内容

  • 没有找到相关文章

最新更新