Регистрация и ожидаемые исключения во время тестирования - PullRequest
1 голос
/ 16 марта 2019

В моем коде приложения часто бывает так, что когда что-то идет не так во время использования приложения, я хочу получить как можно больше информации об обстоятельствах, которые должны быть зарегистрированы, включая, если применимо, трассировку стека Exception, который был брошен.

Но во время тестирования я не хочу, чтобы эти следы стека регистрировались, бесполезно захламляя файл журнала.

Если в этой ситуации сам тест создает объект Exception, то выпотенциально может дать ему сообщение, которое может идентифицировать его как фиктивную Exception, например:

given:
    indexMgr.queryParser = Mock( QueryParser ){
        parse(_) >> { throw new Exception( 'dummy parse problem' )}
    }

, а затем в коде приложения сделать это:

try {
    query = queryParser.parse(queryString)
}catch( e ) {
    log.debug( "QP exception msg: $e.message" )

    // we don't want a stack trace to be logged if this is a dummy Exception deliberately thrown during testing
    if( ! e.message.contains( 'dummy' )) {
        // this will log the stack trace of e
        log.error( 'query threw Exception in QP.parse()', e )
    }
    return false
}

...но с этим есть две проблемы: во-первых, это не всегда тот случай, когда ожидаемый Exception будет создаваться кодом тестирования, а не кодом приложения, и во-вторых, он считает неправильным проверку условий, определяющих поведениетеста в реальном коде приложения.

Есть ли "лучший метод" для решения этой проблемы?

1 Ответ

1 голос
/ 17 марта 2019

Если просто удалить трассировку стека из строки, можно настроить логику преобразования исключений в макете шаблона регистратора. Ниже приведен пример использования log4j2:

public class ExceptionOutput {
    private static final Logger LOG = LoggerFactory.getLogger(ExceptionOutput.class);

    public static void main(String[] args) {
        LOG.info("Foo", new NullPointerException("MESSAGE"));
    }
}

log4j2 конфигурация:

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
    <Appenders>
        <Console name="Console" target="SYSTEM_OUT">
            <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"
                           alwaysWriteExceptions="false"/>
        </Console>
    </Appenders>
    <Loggers>
        <Root level="info">
            <AppenderRef ref="Console"/>
        </Root>
    </Loggers>
</Configuration>

Обратите внимание на alwaysWriteExceptions=false. Он полностью отключает вывод исключений. Теперь, если мы запустим код, мы получим:

01:04:50.151 [main] INFO  ExceptionOutput - Foo

Но если вы вернетесь к alwaysWriteExceptions=true, что также является поведением по умолчанию, если параметр не указан, вы получите:

01:07:03.018 [main] INFO  ExceptionOutput - Foo
java.lang.NullPointerException: MESSAGE
    at ExceptionOutput.main(ExceptionOutput.java:8)

Но это еще не все. Для большей гибкости вы можете использовать %throwable{...} слово преобразования в шаблоне, как объяснено здесь в таблице шаблонов для соответствующего шаблона преобразования. Чтобы применить логику только к тестам, у вас может быть log4j2-test.xml на вашем пути к классам, как объяснено здесь . Аналогичная функциональность преобразования исключений также существует для других библиотек журналов, например, Logback

...