Scala:如何测试调用 System.exit() 的方法?
Scala: How to test methods that call System.exit()?
我一直在开发一个命令行工具,它在某些输入上调用 System.exit()
(不想使用异常而不是 )。
我熟悉Java: How to test methods that call System.exit()? and its the most elegant approach。
不幸的是,它还不够纯粹,因为我不得不将依赖项添加到 system-rules, junit-interface
在 specs2 中是否有处理 System.exit
的通用模式,它比我目前不使用 specs2[ 的方法更纯粹=28=]?
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"});
}
}
第一个选项:使用一些例外而不是 System.exit
。
第二个选项:在单独的线程中调用应用程序并检查 return 代码。
第三个选项:mock System.exit
。有很多种可能,提到一个就很好
但是,没有 specs2
特定的模式可用于 System.exit
。我个人建议第一个或第二个选项。
如果您真的希望使用使用 System.exit()
的方法,测试它实际被调用的最简单方法是将您的 SecurityManager
替换为会抛出 ExitException
(subclassing SecurityException
) 当调用 System.exit()
时:
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)
}
测试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
}
}
我一直在开发一个命令行工具,它在某些输入上调用 System.exit()
(不想使用异常而不是 )。
我熟悉Java: How to test methods that call System.exit()? and its the most elegant approach。
不幸的是,它还不够纯粹,因为我不得不将依赖项添加到 system-rules, junit-interface
在 specs2 中是否有处理 System.exit
的通用模式,它比我目前不使用 specs2[ 的方法更纯粹=28=]?
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"});
}
}
第一个选项:使用一些例外而不是 System.exit
。
第二个选项:在单独的线程中调用应用程序并检查 return 代码。
第三个选项:mock System.exit
。有很多种可能,提到一个就很好
但是,没有 specs2
特定的模式可用于 System.exit
。我个人建议第一个或第二个选项。
如果您真的希望使用使用 System.exit()
的方法,测试它实际被调用的最简单方法是将您的 SecurityManager
替换为会抛出 ExitException
(subclassing SecurityException
) 当调用 System.exit()
时:
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)
}
测试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
}
}