We are testing for exceptions in our unit tests
@Test(expected=IOException.class)
public void test() {
// run some code that throws IOException.
}
The test is passing but as a part of the maven build that runs the test, the stacktrace comes in the console output. Is there anyway in which this stacktrace can be ignored in the tests.
If you want to cover the code in the catch block, your test needs to cause an exception to be thrown in the try block. You will have to setup your test such that it will throw an exception.
JUnit provides an option of tracing the exception handling of code. You can test whether the code throws a desired exception or not. The expected parameter is used along with @Test annotation. Let us see @Test(expected) in action.
Since it looks like InvalidRomanNumberException is a checked exception, you have to either surround it with a try-catch or declare that the method throws InvalidRomanNumberException . JUnit or not, this is the norm.
When using JUnit 4, we can simply use the expected attribute of the @Test annotation to declare that we expect an exception to be thrown anywhere in the annotated test method. In this example, we've declared that we're expecting our test code to result in a NullPointerException.
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.7.1</version>
<configuration>
<redirectTestOutputToFile>true</redirectTestOutputToFile>
</configuration>
</plugin>
Place the above code into your pom.xml's plugins section. redirectTestOutputToFile
will remove the stacktrace from the console output. Obviously, replace the version of surfire with the version you are using.
BTW the redirectTestOutputToFile
parameter is available in the failsafe plugin as well, so you can apply this to your integration tests in the same fashion.
There isn't a nice way to do this, and it's not worth it anyway. I assume that the printed stacktrace is coming from the called code, and not from your test code:
public class ExpectedExceptionTest {
@Test(expected = IOException.class)
public void test() throws Exception {
foobar();
}
public void foobar() throws IOException {
try {
throw new IOException();
} catch (IOException e) {
e.printStackTrace(System.err);
throw e;
}
}
}
Here, the stacktrace which appears in the maven build log is coming from the error handling of the method that you're trying to test. You don't want to change this error handling. If the test fails, then you want to know what's happened.
If you change it, then it also complicates the code under test unnecessarily. Apart from this specific test, you always want the stacktrace to appear.
So, can we set System.err to be null, as was suggested elsewhere? No. If you call
System.setErr(null);
Then this will result in a NullPointerException
(with the above error handling).
If you use log4j or similar for your logging, then you can have a @Rule
which temporarily sets the logging level to INFO so that the exception doesn't appear in your logs. Again, the debug won't appear when you need it most, if the test fails.
I get these exception stacktraces all of the time in my project build output(s). I just accept it and congratulate myself that I'm testing error conditions correctly :-)
System.err is what that gets printed to, and it is a PrintStream which can be modified at runtime. So in the System.err, put a new PrintStream made from an OutputStream that prints out nothing when write(int i)
is called:
System.setErr(new PrintStream(new OutputStream(){public void write(int i){}}));
Remember to backup the current PrintStream in System.err though after you're done suppressing output, or else you won't receive other errors that might actually be useful to know about.
You can backup and set the fake on in BeforeClass and restore in AfterClass or something like that.
Additional notes:
Here's a fuller set of lines you can put in your test:
java.io.PrintStream realErrorStream = System.err;
System.setErr(new java.io.PrintStream(new java.io.OutputStream(){public void write(int i){}}));
...
System.setErr(realErrorStream);
y solution to assert that I actually catch expected Exception without seeing stacktrace is
@Test
public void test() {
try {
// run some code that throws IOException.
} catch (Exception ex) {
assertTrue(ex.getClass().equals(IOException.class));
}
}
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