Java:如何测试调用System.exit()的方法?

我有一些方法可以对某些输入调用System.exit()。不幸的是,测试这些案例会导致JUnit终止!将方法调用放入新线程似乎没有帮助,因为System.exit()终止JVM,而不仅仅是当前线程。处理这个问题有什么共同的模式吗?例如,我可以为System.exit()替换存根吗

[EDIT]这个类实际上是一个命令行工具,我正试图在JUnit中测试它。也许JUnit根本不是适合这项工作的工具?欢迎提供补充回归测试工具的建议(最好是与JUnit和EclEmma很好集成的工具)

事实上,Derkeiler.com建议:

  • 为什么System.exit()

与其用System.exit(whateverValue)终止,为什么不抛出一个未检查的异常呢?在正常使用中,它会一直漂移到JVM的最后一个捕获器,并关闭脚本(除非您决定在某个地方捕获它,这可能有一天会有用)

在JUnit场景中,它将被JUnit框架捕获,该框架将报告
这样那样的测试失败了,顺利地进行了下一个测试

  • 阻止System.exit()实际退出JVM:

尝试修改TestCase,使其与阻止调用System.exit的安全管理器一起运行,然后捕获SecurityException

公共类NoExitTestCase扩展了TestCase
{
受保护的静态类ExitException扩展了SecurityException
{
公众最终身份;
公共ExitException(int状态)
{
超级(“没有逃脱的机会!”);
这个状态=状态;
}
}
私有静态类NoExitSecurityManager扩展了SecurityManager
{
@凌驾
公共作废检查权限(权限perm)
{
//允许任何事情。
}
@凌驾
public void checkPermission(权限perm、对象上下文)
{
//允许任何事情。
}
@凌驾
公共无效检查退出(int状态)
{
超级。检查退出(状态);
抛出新的ExitException(状态);
}
}
@凌驾
受保护的void setUp()引发异常
{
super.setUp();
System.setSecurityManager(新的NoExitSecurityManager());
}
@凌驾
受保护的void tearDown()引发异常
{
System.setSecurityManager(null);//或保存并还原原始文件
super.tearDown();
}
public void testNoExit()引发异常
{
System.out.println(“打印作品”);
}
public void testExit()引发异常
{
尝试
{
系统出口(42);
}捕获(出口)
{
资产质量(“退出状态”,42,e.状态);
}
}
}


2012年12月更新:

威尔在评论中使用系统规则提出了一组JUnit(4.9+)规则,用于测试使用java.lang.System的代码
Stefan Birkner在2011年12月的回答中首次提到了这一点

系统。退出(…)

使用ExpectedSystemExit规则验证是否调用了System.exit(…)
您也可以验证退出状态

例如:

公共无效MyTest{
@统治
public final ExpectedSystemExit=ExpectedSystemExit.none();
@试验
公共无效无系统退出(){
//通行证
}
@试验
公共无效系统ExitWithArbitraryStatusCode(){
expectSystemExit();
系统出口(0);
}
@试验
public void systemExitWithSelectedStatusCode0(){
退出。expectSystemExitWithStatus(0);
系统出口(0);
}
}

发表评论