How to fail JUnit tests if the Java process exits with non-zero exit code?

Viewed 220

In a desperate attempt to properly test my Java code, which includes being aware of any unhandled exception, I routinely use setUncaughtExceptionHandler for my worker threads, which intercepts exceptions, makes some noise and calls System.exit(1) which I notice (in Java by default non-main threads are OK(!) to die at any point if they encounter an exception - they will do so silently i.e. without bringing down the process).

My problem is JUnit5 (with gradle) reports a test that dies in this way, as "SKIPPED" aka Ignored, rather that failed. To my surprise, the testsuite reports SUCCESS. Googling "make junit fail on System.exit" doesnt't help. What am I missing? How to make JUnit fail in such circumstances?

1 Answers

I have read an article before. It looks good and may be helpful to you: https://todd.ginsberg.com/post/testing-system-exit/

First of all, I agree this idea very much:

Writing a unit test that actually exits the JVM while it is under test is definitely not ideal.

In order to avoid that this article becomes invalid one day, I'll quote some of the content first:

Whenever the JVM does something interesting (like exiting, or reading a file), it first checks whether it has permission to do so. This is done by consulting the SecurityManager the system is using. One of the methods on SecurityManager is checkExit(). If that method throws a SecurityException, it means the system is not allowed to exit at this point. Conveniently, checkExit() takes one argument - the exit status code being attempted.

Now that we know that, we can form a plan of action:

  1. Write a SecurityManager that always prevents System.exit(), and records the code attempted.
  2. Any other call to our SecurityManager should delegate to whatever SecurityManager was being used by the system before our test started.
  3. Integrate this with JUnit 5, via the Extension model.

If you need the full code, plz read that article

Related