2012-02-16 13 views
15

Tenemos un Groovy Script que sale con un status de 0 cuando todo funcionó y un non-0 status para diferentes tipos de condiciones de falla. Por ejemplo, si el script tomó un usuario y una dirección de correo electrónico como argumentos, saldría con un status de 1 para un usuario no válido y un status de 2 para un formato de dirección de correo electrónico no válido. Usamos System.exit(statusCode) para esto. Esto funciona bien, pero hace que el guión sea difícil de escribir.Cómo establecer el estado de salida en un Groovy Script

En una prueba creamos nuestro GroovyShell, cree nuestro Binding y llame al shell.run(script,args). Para las pruebas que afirman las condiciones de falla, el System.exit() hace que la JVM (y la prueba) salgan.

¿Hay alternativas al uso de System.exit() para salir de Groovy Script? Experimenté con lanzar excepciones no capturadas, pero que estorba la salida y siempre hace que el código de estado 1.

En nuestros casos de prueba También he experimentado con el uso System.metaClass.static.invokeMethod para cambiar el comportamiento de System.exit() a no salir de la JVM, pero que parece como un feo truco.

Respuesta

9

imho System.metaClass.static.invokeMethod se ve bien. Es una prueba, y el pirateo está bien aquí.

También usted puede crear su propio envoltorio alrededor de ella, como:

class ExitUtils { 

    static boolean enabled = true 

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

} 

y desactivarlo para las pruebas.

+0

Gracias. Limpié nuestro trabajo 'System.metaClass.static.invokeMethod' y parecía mucho menos hacky. – Patrick

4

Esta es la técnica que finalmente utilizamos.

No podemos simplemente ignorar una llamada a System.exit() ya que la secuencia de comandos continuará ejecutándose. En su lugar, queremos lanzar una excepción con el código de estado deseado. Nos tiramos un (a medida) ProgramExitException cuando System.exit() se llama en nuestras pruebas

class ProgramExitException extends RuntimeException { 

    int statusCode 

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

entonces interceptar System.exit() para lanzar esta excepción

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

y por último tenemos GroovyShell captura cualquier ProgramExitException y devolver el código de estado de el método 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) 
    } 
} 

Nuestras pruebas pueden permanecer aspecto sencillo, no es necesario cambiar nada en los guiones y obtenemos el comportamiento que se espera de ejecución en la línea de comandos.

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