为什么Mockito对InputStreams表现得很奇怪?

时间:2016-05-02 15:26:44

标签: java unit-testing mockito stubbing

在调试过程中,我发现使用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方法失败的方式和原因的任何帮助都会非常棒。

2 个答案:

答案 0 :(得分:2)

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

您可以更改default mock behaviour或手动添加读取(buff)方法的定义。

答案 1 :(得分:1)

你想要设置你的模拟器,以便在你没有存根时调用InputStream的真实方法

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

javadoc

  

使用旧代码时,此实现很有帮助。什么时候   使用此实现, unstubbed方法将委托给   真正的实施。这是一种创建部分模拟对象的方法   默认情况下调用实际方法。

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

通过使用Mockito.CALLS_REAL_METHODS,您告诉Mockito在InputStream中调用实际的实现,该read()会委托给您const initialState = { fetching: false, }; export function reducer(state = initialState, action) { switch(action.type) { case 'LOAD_FETCHING': return { ...state, fetching: action.fetching, } } } ,而您已将其隐藏起来异常。