使Logback在ERROR级别的日志事件上抛出异常

使Logback在ERROR级别的日志事件上抛出异常

本文介绍了使Logback在ERROR级别的日志事件上抛出异常的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在运行单元测试时,我想在记录错误级别消息的任何测试中失败.使用SLF4J/Logback实现此目的的最简单方法是什么?我想避免编写自己的ILoggerFactory实现.

When running unit tests, I'd like to fail any tests during which ERROR level message is logged. What would be the easiest way to achieve this using SLF4J/Logback? I'd like to avoid writing my own ILoggerFactory implementation.

我尝试编写自定义的Appender,但是我无法通过调用Appender的代码传播异常,所有来自Appender的异常都被捕获在那里.

I tried writing a custom Appender, but I cannot propagate exceptions through the code that's calling the Appender, all exceptions from Appender get caught there.

推荐答案

关键是编写自定义附加程序.您没有说要使用哪个单元测试框架,但是对于JUnit,我需要做类似的事情(它比所有错误都要复杂一点,但基本上是相同的概念),并创建了一个JUnit @Rule,添加了我的appender ,追加程序将根据需要通过测试.

The key is to write a custom appender. You don't say which unit testing framework you use, but for JUnit I needed to do something similar (it was a little more complex than just all errors, but basically the same concept), and created a JUnit @Rule that added my appender, and the appender fails the test as needed.

我将此答案的代码放置在公共领域:

I place my code for this answer in the public domain:

import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.Logger;
import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.AppenderBase;
import org.junit.rules.ExternalResource;
import org.slf4j.LoggerFactory;
import static org.junit.Assert.fail;

/**
 * A JUnit {@link org.junit.Rule} which attaches itself to Logback, and fails the test if an error is logged.
 * Designed for use in some tests, as if the system would log an error, that indicates that something
 * went wrong, even though the error was correctly caught and logged.
 */
public class FailOnErrorLogged extends ExternalResource {

    private FailOnErrorAppender appender;

    @Override
    protected void before() throws Throwable {
        super.before();
        final LoggerContext loggerContext = (LoggerContext)(LoggerFactory.getILoggerFactory());
        final Logger rootLogger = (Logger)(LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME));
        appender = new FailOnErrorAppender();
        appender.setContext(loggerContext);
        appender.start();
        rootLogger.addAppender(appender);
    }

    @Override
    protected void after() {
        appender.stop();
        final Logger rootLogger = (Logger)(LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME));
        rootLogger.detachAppender(appender);
        super.after();
    }

    private static class FailOnErrorAppender extends AppenderBase<ILoggingEvent> {
        @Override
        protected void append(final ILoggingEvent eventObject) {
            if (eventObject.getLevel().isGreaterOrEqual(Level.ERROR)) {
                fail("Error logged: " + eventObject.getFormattedMessage());
            }
        }
    }
}

用法示例:

import org.junit.Rule;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class ExampleTest {
    private static final Logger log = LoggerFactory.getLogger(ExampleTest.class);

    @Rule
    public FailOnErrorLogged failOnErrorLogged = new FailOnErrorLogged();

    @Test
    public void testError() {
        log.error("Test Error");
    }

    @Test
    public void testInfo() {
        log.info("Test Info");
    }
}

testError方法失败,并且testInfo方法通过.如果测试调用的真实被测类也记录了错误,则其工作原理相同.

The testError method fails and the testInfo method passes. It works the same if the test calls the real class-under-test that logs an error as well.

这篇关于使Logback在ERROR级别的日志事件上抛出异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-25 00:52