2012-02-16 2226 views
15

我们有一个Groovy脚本,当的0有效时退出,non-0 status对于不同类型的故障条件。例如,如果脚本以用户和电子邮件地址作为参数,则对于无效的用户,将退出status1,对于无效的电子邮件地址格式,则退出status2。我们为此使用System.exit(statusCode)。这工作正常,但使脚本很难编写测试用例。如何在Groovy脚本中设置退出状态

在测试中,我们创造我们GroovyShell,创造我们Binding并调用shell.run(script,args)。对于断言失败条件的测试,System.exit()会导致JVM(和测试)退出。

是否有其他方法可以使用System.exit()退出Groovy脚本?我尝试用抛出未捕获的异常,但杂波的输出和总是让状态码1

在我们的测试情况下,我也尝试用System.metaClass.static.invokeMethod改变System.exit()行为不退出JVM,但似乎像一个丑陋的黑客。

回答

9

imho System.metaClass.static.invokeMethod看起来不错。这是测试,黑客在这里很好。

你也可以创建自己包装它周围,如:

class ExitUtils { 

    static boolean enabled = true 

    static exit(int code) { 
     if (!ExitUtils.enabled) { 
      return //TODO set some flag? 
     } 
     System.exit(code) 
    } 

} 

,同时禁用测试。

+0

谢谢。我清理了我们的'System.metaClass.static.invokeMethod'工作,而且看起来不那么黑客。 – Patrick 2012-02-18 00:32:51

4

这是我们最终使用的技术。

因为脚本会继续运行,所以我们不能忽略对System.exit()的调用。相反,我们想用所需的状态码抛出一个异常。我们抛出一个(自定义)ProgramExitExceptionSystem.exit()被称为在我们的测试中

class ProgramExitException extends RuntimeException { 

    int statusCode 

    public ProgramExitException(int statusCode) { 
     super("Exited with " + statusCode) 
     this.statusCode = statusCode 
    } 
} 

然后我们截取System.exit()抛出该异常

/** 
* Make System.exit throw ProgramExitException to fake exiting the VM 
*/ 
System.metaClass.static.invokeMethod = { String name, args -> 
    if (name == 'exit') 
     throw new ProgramExitException(args[0]) 
    def validMethod = System.metaClass.getStaticMetaMethod(name, args) 
    if (validMethod != null) { 
     validMethod.invoke(delegate, args) 
    } 
    else { 
     return System.metaClass.invokeMissingMethod(delegate, name, args) 
    } 
} 

,最后我们有GroovyShell捕捉任何ProgramExitException,并从返回的状态代码run方法。

/** 
* Catch ProgramExitException exceptions to mimic exit status codes 
* without exiting the VM 
*/ 
GroovyShell.metaClass.invokeMethod = { String name, args -> 
    def validMethod = GroovyShell.metaClass.getMetaMethod(name, args) 
    if (validMethod != null) { 
     try { 
      validMethod.invoke(delegate, args) 
     } catch (ProgramExitException e) { 
      return e.statusCode 
     } 
    } 
    else { 
     return GroovyShell.metaClass.invokeMissingMethod(delegate, name, args) 
    } 
} 

我们的测试可以留在寻找简单,我们不需要更改任何脚本,我们得到我们在命令行中运行预期的行为。

assertEquals 'Unexpected status code', 0, shell.run(script,[arg1, arg2]) 
assertEquals 'Unexpected status code', 10, shell.run(script,[badarg1, badarg2])