Scala:如何测试调用System.exit()的方法?
我一直在开发一个命令行工具,它可以在某些输入上调用Scala:如何测试调用System.exit()的方法?,scala,unit-testing,sbt,specs2,testability,Scala,Unit Testing,Sbt,Specs2,Testability,我一直在开发一个命令行工具,它可以在某些输入上调用System.exit()(不想使用异常代替) 我很熟悉,它是最优雅的 不幸的是,它不够纯净,因为我不得不将依赖项添加到 是否有处理系统的通用模式。在规范2中退出,这比我目前不使用规范2中的方法更纯粹 import org.junit.Rule; import org.junit.Test; import org.junit.contrib.java.lang.system.ExpectedSystemExit; public class Co
System.exit()
(不想使用异常代替)
我很熟悉,它是最优雅的
不幸的是,它不够纯净,因为我不得不将依赖项添加到
是否有处理系统的通用模式。在规范2中退出,这比我目前不使用规范2中的方法更纯粹
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"});
}
}
第一个选项:使用一些异常而不是系统。退出
第二个选项:在单独的线程中调用应用程序并检查返回代码
第三个选项:模拟系统。退出。有很多种可能性可以做到这一点,提到的一个是相当好的
但是,没有可用于系统的规范2
特定模式。退出。就个人而言,我建议您选择第一个或第二个选项。如果您真的希望使用System.exit()
的方法,最简单的测试方法是将SecurityManager
替换为在System.exit()时抛出ExitException
(子类化SecurityException
)的方法
称为:
classSystemExitSpec
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
}
}
测试转换器规格
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
}
}
1.第一种选择对我来说是不可接受的。2.第二个选项对我来说有点过于复杂,比系统规则3更复杂。第三个选项-与之前的IMO相同,使用系统规则是简洁的,只是它不使用specs2:(对于第三个选项,您可以使用模拟静态类的模拟库,例如PowerMock。另一个选项是提供/注入一个本身调用system.exit()的简单组件),并通过标准模拟框架断言该组件被正确调用。我可能错过了这一部分。不过,最好有myObject。myfunctionexit()必须是throwAn(ExitException(1))
很抱歉弄糟了,您应该恢复上次更改,我们必须使用您的建议,为什么?因为specs2没有验证状态。code,由于存在异常,您可以检查异常消息,对吗?或者简单地使用必须通过[ExitException]
我可以使用必须通过[ExitException]
,但这与try不同{myObject.myFunctionExitting()失败(“不应该读取此代码”)}catch{case e:ExitException=>e.status must==1}签出,其中Bill Venners(ScalaTest的作者)提供了一个有用的答案。