How to check SystemExit and SystemOut
tomaculum opened this issue · 4 comments
Hi all,
currently I am converting my tests from JUnit 4 to JUnit 5 but I have a bit of an issue with the following test:
// JUnit 4
@Rule
public final SystemOutRule systemOutRule = new SystemOutRule().enableLog().mute();
@Rule
public final ExpectedSystemExit exit = ExpectedSystemExit.none();
@Rule
public ExpectedException exceptionRule = ExpectedException.none();
@Test()
public void testExample() {
exit.expectSystemExit();
exit.checkAssertionAfterwards(() -> {
assertThat(systemOutRule.getLog(), is("OutputWithExit\n"));
systemOutRule.clearLog();
});
Example.main();
assertThat(systemOutRule.getLog(), is("OutputWithoutExit"));
systemOutRule.clearLog();
}
How do I achieve a similar result in JUnit 5 with the new system-lambda
library?
Ignoring the SystemExit and just checking the SystemOut terminates some of my other running tests. And even running it independently does not work as expected.
This was my naive attempt to combine those two but even with fail()
it results in a passed test.
// JUnit 5
@Test()
public void testExample() throws Exception {
int status = SystemLambda.catchSystemExit(() -> {
String text = tapSystemOut(() -> Example.main());
fail();
});
}
I do not necessarily need to check those two cases in one test but it should not terminate my other tests. Hope this makes kind of sense.
TLDR; change the order and the test will work:
@Test
public void testExample() throws Exception {
var text = tapSystemOut(() -> {
catchSystemExit(Example::main);
});
assertThat(text, is("OutputWithExit\n"));
}
Your approach does not work because Example.main()
calls System.exit()
. Because of catchSystemExit
an exception is thrown when System.exit()
is called. This exception is rethrown by tapSystemOut
(therefore fail()
is not executed) and catched by catchSystemExit
which extract the exit status and returns it.
IMO this is not a bug but it requires some documentation updates.
FYI The two lines after Example.main()
are never executed. With System Rules all code that comes after the code that calls System.exit()
is not executed.
It works, thank you very much!
Do you want to keep this issue open because of the documentation updates? From my side, this issue can be closed.
You can close it. I will create a new release that tackles the problem with better documentation and a helpful error message (if possible).