I've scoured through StackOverflow for the same types of questions, and checked each response, but still facing this problem. I am testing for a IOException to be thrown from a method called readStream(), and the method does throw the IOException, but Junit fails the test with an AssertionException.
private static StringBuilder readStream(InputStream inputStream) throws IOException {
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
StringBuilder stringBuilder = new StringBuilder();
String line;
try {
while ((line = reader.readLine()) != null){
stringBuilder.append(line + "\n");
}
} catch (IOException e) {
e.printStackTrace();
throw e;
}
finally {
try{
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return stringBuilder;
}
Here is my unit test:
@SpringBootTest(classes = RequestResponseUtility.class)
public class RequestResponseUtilityTest extends AbstractTest {
@Mock
private InputStream inputStream;
@Test(expected = IOException.class)
public void convertStreamToStringNullTest() throws IOException {
RequestResponseUtility.convertStreamToString(inputStream);
}
}
I've tried, as you see, to have the exception in the original class actually throw the exception, rather than just catch and print the stack trace:
e.printStackTrace();
throw e;
I've also tried both using the annotation @Test(expected=IOException.class) and using the @Rule approach. Both fail the test. I've tried annotating my test with both @SpringBootTest (as you see above) and with @RunWith(springjunit4classrunner.class). I'm really at a loss here. I get this error
java.lang.AssertionError: Expected exception: java.io.IOException
But my stack trace is
java.io.IOException: Underlying input stream returned zero bytes
at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:288)
at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:326)
at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:178)
at java.io.InputStreamReader.read(InputStreamReader.java:184)
at java.io.BufferedReader.fill(BufferedReader.java:161)
at java.io.BufferedReader.readLine(BufferedReader.java:324)
at java.io.BufferedReader.readLine(BufferedReader.java:389)
at main.java.utilities.RequestResponseUtility.readStream(RequestResponseUtility.java:25)
at main.java.utilities.RequestResponseUtility.convertStreamToString(RequestResponseUtility.java:45)
This is breaking my heart. It's not a huge deal and doesn't impact the performance of my code in production, but I want to understand why it's actually happening.
Well, I feel kind of silly because I just solved my own question right after I posted this. I didn't examine the stack trace closely enough:
at main.java.utilities.RequestResponseUtility.readStream(RequestResponseUtility.java:25)
at main.java.utilities.RequestResponseUtility.convertStreamToString(RequestResponseUtility.java:45)
at test.java.utilities.RequestResponseUtilityTest.convertStreamToStringNullTest(RequestResponseUtilityTest.java:42)
The first method that is called is convertStreamToStringNullTest(), my unit test. This calls convertStreamToString(). However, convertStreamToString() actually calls a private helper method inside my RequestResponseUtility class called readStream(). In my question, I had posted the code to readStream(), since I knew intuitively that was where the exception was being thrown.
However, as the exception propagates back down the stack to convertStreamToString(), I never throw the exception. I only print the stack trace. So it gets stuck at that method, and therefore the unit test, which is "listening" for a IOException from convertStreamToString(), never gets the thrown exception!
Moral of the story is to check for nested methods and really trace where your exception should be coming from!