10

我一直在开发一个命令行工具,它在某些输入上调用System.exit()不想使用异常而不是)。

我熟悉Java:如何测试调用 System.exit() 的方法?它是最优雅的方法

不幸的是,它不够纯净,因为我必须将依赖项添加到system-rulesjunit-interface

System.exitspecs2中是否有任何常见的处理模式,它比我目前不使用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"});
    }
}
4

2 回答 2

12

如果您真的希望使用 usingSystem.exit()的方法,测试它实际被调用的最简单方法是将您的替换为在调用时SecurityManager会抛出ExitException(子类化SecurityExceptionSystem.exit()的方法:

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)
}

测试转换器规格

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
    }
}
于 2016-08-22T09:26:47.733 回答
1

第一个选项:使用一些异常而不是System.exit.

第二种选择:在单独的线程中调用应用程序并检查返回码。

第三个选项: mock System.exit。有很多可能性可以做到这一点,提到的一种非常好。

但是,没有specs2特定的模式可以使用System.exit. 我个人建议第一个或第二个选项。

于 2016-08-22T08:23:26.760 回答