I want to test some code that uses 3rd party code that calls kotlin.system.exitProcess()
, defined as follows in the standard lib:
@kotlin.internal.InlineOnly
public inline fun exitProcess(status: Int): Nothing {
System.exit(status)
throw RuntimeException("System.exit returned normally, while it was supposed to halt JVM.")
}
When exitProcess()
is called, the JVM stops and further testing is impossible. I didn't manage to mock calls to exitProcess()
with mockk. Is it possible?
Some further information:
The 3rd party lib is Clikt (https://ajalt.github.io/clikt/), a nice library for building a command line interface. A Clikt application parses the command line, and exits if this fails. This may be one of the rare reasons, where calling System.exit is OK. Surely there are more testable solutions, but anyway, when working with 3rd party libs, arguing what could be better done in the lib is obsolete.
What I actually want to test is, that my application writes the expected usage message when called with --help or wrong arguments.
I also tried to mock the call to System.exit()
this way:
mockkStatic("java.lang.System")
every { System.exit(any()) }.throws(RuntimeException("blubb"))
which leads to another problem, als all calls to System are mocked then:
io.mockk.MockKException: every/verify {} block were run several times. Recorded calls count differ between runs
Round 1: class java.lang.System.getProperty(kotlin.ignore.old.metadata), class java.lang.System.exit(-630127373)
Round 2: class java.lang.System.exit(158522875)
Funnily enough, I managed to test this in Java with jmockit, like this:
public class MainTestJ {
private ByteArrayOutputStream consoleOut;
@BeforeEach
public void mockConsole() {
consoleOut = new ByteArrayOutputStream();
System.setOut(new PrintStream(consoleOut));
}
@Test
public void can_mock_exit() {
new MockUp<System>() {
@Mock
public void exit(int exitCode) {
System.out.println("exit called");
}
};
assertThatThrownBy(() -> {
new Main().main(new String[] { "--help" });
}).isInstanceOf(RuntimeException.class);
assertThat(consoleOut.toString()).startsWith("Usage: bla bla ...");
}
}