Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scala: How to test methods that call System.exit()?

I have been developing a command-line tool which calls System.exit() (don't want to use exceptions instead of) on certain inputs.

I am familiar with Java: How to test methods that call System.exit()? and its the most elegant approach.

Unfortunately, it is not enough pure, due to I had to add the dependencies to system-rules, junit-interface

Is there any common pattern for dealing with System.exit in specs2 which is more pure than my current approach which don't use specs2?

import org.junit.Rule;
import org.junit.Test;
import org.junit.contrib.java.lang.system.ExpectedSystemExit;

public class ConverterTest {
    @Rule
    public final ExpectedSystemExit exit = ExpectedSystemExit.none();

    @Test
    public void emptyArgs() {
        exit.expectSystemExit();
        Converter.main(new String[]{});
    }

    @Test
    public void missingOutArgument() {
        exit.expectSystemExitWithStatus(1);
        Converter.main(new String[]{"--in", "src/test/resources/078.xml.gz"});
    }
}
like image 207
sergiusz.kierat Avatar asked Aug 22 '16 07:08

sergiusz.kierat


People also ask

Can we mock system exit?

You actually can mock or stub out the System. exit method, in a JUnit test. Vote down reason: The problem with this solution is that if System. exit is not the last line in the code (i.e. inside if condition), the code will continue to run.

What is the use of system out exit ()?

System. exit() method. This method terminates the currently running Java Virtual Machine(JVM). It takes an argument “status code” where a non zero status code indicates abnormal termination.

What is method exit?

exit() method terminates the current JVM running on the system which results in termination of code being executed currently. This method takes status code as an argument. exit() method is required when there is an abnormal condition and we need to terminate the program immediately.

What can I use instead of system exit in Java?

The main alternative is Runtime. getRuntime(). halt(0) , described as "Forcibly terminates the currently running Java virtual machine". This does not call shutdown hooks or exit finalizers, it just exits.


2 Answers

If you really wish to go with a method using System.exit(), the simplest way to test it was actually called is to replace your SecurityManager with one that'll throw an ExitException (subclassing SecurityException) when System.exit() is called:

class SystemExitSpec

import java.security.Permission

import org.specs2.mutable.Specification
import org.specs2.specification.BeforeAfterAll

sealed case class ExitException(status: Int) extends SecurityException("System.exit() is not allowed") {
}

sealed class NoExitSecurityManager extends SecurityManager {
  override def checkPermission(perm: Permission): Unit = {}

  override def checkPermission(perm: Permission, context: Object): Unit = {}

  override def checkExit(status: Int): Unit = {
    super.checkExit(status)
    throw ExitException(status)
  }
}


abstract class SystemExitSpec extends Specification with BeforeAfterAll {

  sequential

  override def beforeAll(): Unit = System.setSecurityManager(new NoExitSecurityManager())

  override def afterAll(): Unit = System.setSecurityManager(null)
}

test ConverterSpec

import org.specs2.execute.Failure

import scala.io.Source

class ConverterSpec extends SystemExitSpec {

"ConverterSpec" should {

    "empty args" >> {
      try {
        Converter.main(Array[String]())
        Failure("shouldn't read this code")
      } catch {
        case e: ExitException =>
          e.status must_== 1
      }
      1 must_== 1
    }
}
like image 132
Ven Avatar answered Oct 19 '22 16:10

Ven


First option: use some exception instead of System.exit.

Second option: call application in separate thread and check return codes.

Third option: mock System.exit. There are many possibilities to do that, mentioned one is quite good.

However, there is no specs2-specific pattern to work with System.exit. Personally I'd suggest first or second options.

like image 25
dveim Avatar answered Oct 19 '22 16:10

dveim