这是我们最终使用的技术。
因为脚本会继续运行,所以我们不能忽略对System.exit()
的调用。相反,我们想用所需的状态码抛出一个异常。我们抛出一个(自定义)ProgramExitException
时System.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])
谢谢。我清理了我们的'System.metaClass.static.invokeMethod'工作,而且看起来不那么黑客。 – Patrick 2012-02-18 00:32:51