2012-02-16 18 views
15

Abbiamo uno script Groovy che esce con uno status di 0 quando tutto funziona e uno non-0 status per diversi tipi di condizioni di errore. Ad esempio, se lo script ha preso un utente e un indirizzo email come argomenti, esso uscirebbe con un status di 1 per un utente non valido e uno status di 2 per un formato di indirizzo di posta elettronica non valido. Per questo usiamo System.exit(statusCode). Funziona bene, ma rende lo script difficile da scrivere per i casi di test.Come impostare lo stato di uscita in uno script Groovy

In un test creiamo il nostro GroovyShell, crea il nostro Binding e chiama shell.run(script,args). Per i test che affermano condizioni di errore, lo System.exit() causa l'uscita dalla JVM (e dal test).

Esistono alternative all'utilizzo di System.exit() per uscire da un Groovy Script? Ho sperimentato con generazione di eccezioni non gestite fanno, ma che ingombra l'uscita e fa sempre il codice di stato 1.

Nei nostri casi di test Ho anche sperimentato con l'utilizzo di System.metaClass.static.invokeMethod per modificare il comportamento di System.exit() di non uscire dalla JVM, ma che sembra come un brutto scherzo.

risposta

9

imho System.metaClass.static.invokeMethod sembra buono. È un test, e l'hacking va bene qui.

Inoltre è possibile creare il proprio involucro attorno ad esso, come:

class ExitUtils { 

    static boolean enabled = true 

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

} 

e disattivarla per i test.

+0

Grazie. Ho ripulito il nostro lavoro 'System.metaClass.static.invokeMethod' e sembrava molto meno hacky. – Patrick

4

Ecco la tecnica che abbiamo usato.

Non possiamo semplicemente ignorare una chiamata a System.exit() poiché lo script continuerà a essere eseguito. Invece vogliamo lanciare un'eccezione con il codice di stato desiderato. Gettiamo un (personalizzato) ProgramExitException quando System.exit() è chiamato nei nostri test

class ProgramExitException extends RuntimeException { 

    int statusCode 

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

poi intercettare System.exit() di lanciare questa eccezione

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

ed infine abbiamo GroovyShell cattura qualsiasi ProgramExitException e restituire il codice di stato da il metodo 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) 
    } 
} 

I nostri test possono rimanere alla ricerca semplice, non abbiamo bisogno di cambiare qualcosa negli script e otteniamo il comportamento che ci aspettiamo di correre sulla riga di comando.

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