2012-02-16 21 views
15

Groovyスクリプトは、すべての作業が完了したときに、終了タイプがnon-0 statusstatusで終了します。たとえば、スクリプトがユーザーとメールアドレスを引数として受け取った場合、無効なユーザーの場合はstatus1、無効なメールアドレスの場合はstatus2で終了します。これにはSystem.exit(statusCode)を使用します。これはうまくいきますが、スクリプトをテストケースを書くのが難しくなります。Groovyスクリプトで終了ステータスを設定するには

テストではGroovyShellを作成し、Bindingを作成してshell.run(script,args)としてください。障害状態をアサートするテストの場合、System.exit()はJVM(およびテスト)を終了させます。

System.exit()を使用してGroovyスクリプトを終了する方法はありますか?私はキャッチされていない例外を投げて実験しましたが、出力を混乱させ、常にステータスコード1を生成します。

System.metaClass.static.invokeMethodを使用して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

4

最終的に使用した技術は次のとおりです。

System.exit()の呼び出しを無視することはできません。スクリプトは引き続き実行されるためです。代わりに、目的のステータスコードで例外をスローする必要があります。私たちは、System.exit()が我々のテスト

class ProgramExitException extends RuntimeException { 

    int statusCode 

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

に呼び出されたとき、我々は

/** 
* 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) 
    } 
} 

この例外をスローするSystem.exit()を傍受し、最後に私たちはGroovyShellキャッチに何かProgramExitExceptionを持ってからステータスコードを返します(カスタム)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]) 
関連する問題