While debugging I came across something incredibly strange using Mockito 1.10. I was hoping someone could explain the behavior perceived here:
When I run the following, my thread hangs and my test never returns. CPU of the Java process created goes astronomical too!
@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());
}
When I manually stub this method as follows, the expected IOException is thrown:
@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());
}
Any help understanding how and why the mockito method is failing would be fantastic.
If you take a look at the ByteStreams implementation, you can see that the read(buf) method is used. In your case it returns null because there is no mock definition for it and this causes an endless loop in the copy method.
You may either change the default mock behaviour or manually add a definition for the read(buff) method.
You'll want to set up your mock to call the real methods of InputStream
when you haven't stubbed them
final InputStream mis = Mockito.mock(InputStream.class, Mockito.CALLS_REAL_METHODS);
The javadoc states
This implementation can be helpful when working with legacy code. When this implementation is used, unstubbed methods will delegate to the real implementation. This is a way to create a partial mock object that calls real methods by default.
Mockito, by default, mocks everything. The ByteStreams#copy
method you used first invokes InputStream#read(byte[])
. Since mockito has mocked it, it will return 0 which ByteStreams#copy
interprets as "there is more to read from this stream" and keeps reading (infinite loop).
By using Mockito.CALLS_REAL_METHODS
, you're telling Mockito to call the actual implementation in InputStream
, which will delegate to read()
, which you've stubbed to throw an exception.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With