【问题标题】:Logging and expected Exceptions during testing测试期间的日志记录和预期异常
【发布时间】:2019-03-16 05:00:34
【问题描述】:

在我的应用程序代码中,在应用程序使用过程中出现问题的地方很常见,我希望尽可能多地记录有关情况的信息,包括如果适用,包括已抛出的 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 并非总是由测试代码而不是应用程序代码创建的,其次是感觉不对检查在实际应用代码中识别测试行为的条件。

是否有解决此问题的“最佳实践”方法?

【问题讨论】:

    标签: testing exception logging spock


    【解决方案1】:

    如果只是从一行中删除堆栈跟踪就可以了,您可以在记录器的模式布局中配置异常转换逻辑。下面是一个使用 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{...} 转换字,如模式表中here 中针对相应转换模式的说明。为了仅将逻辑应用于测试,您可以在类路径中包含 log4j2-test.xml,如 here 所述。其他日志库也存在类似的异常转换功能,例如logback

    【讨论】:

    • 谢谢...非常有帮助。我想如果没有一些人为的机制来告诉应用程序代码正在进行测试,那么更细粒度的解决方案可能是不可能的。只是您可能希望正确记录意外异常(在测试和应用程序代码中)......但要抑制预期的异常。
    猜你喜欢
    • 2011-04-30
    • 2011-03-03
    • 2012-11-15
    • 1970-01-01
    • 2019-01-23
    • 1970-01-01
    • 1970-01-01
    • 2018-01-17
    • 1970-01-01
    相关资源
    最近更新 更多