Как установить статус выхода в скрипте Groovy
У нас есть Groovy Script, который выходит с status
из 0
когда все работало и non-0 status
для разных типов условий отказа. Например, если скрипт взял в качестве аргументов пользователя и адрес электронной почты, он завершился бы с status
из 1
для недопустимого пользователя и status
из 2
для неверного формата адреса электронной почты. Мы используем System.exit(statusCode)
за это. Это прекрасно работает, но делает сценарий трудным для написания тестовых случаев.
В тесте мы создаем наш GroovyShell
, создайте наш Binding
и позвонить shell.run(script,args)
, Для тестов, которые утверждают условия отказа, System.exit()
заставляет JVM (и тест) выйти.
Есть ли альтернативы использованию System.exit()
выйти из Groovy Script? Я экспериментировал с генерацией необработанных исключений, но это загромождает вывод и всегда делает код состояния 1.
В наших тестах я также экспериментировал с использованием System.metaClass.static.invokeMethod
изменить поведение System.exit()
не выходить из JVM, но это похоже на уродливый хак.
2 ответа
По моему мнению 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)
}
}
и отключите его для тестов.
Вот техника, которую мы в конечном итоге использовали.
Мы не можем просто игнорировать звонок 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])