如何通过 JUnit 测试拦截 SLF4J(带 logback)日志记录?

新手上路,请多包涵

是否有可能以某种方式拦截日志记录(SLF4J + logback)并通过 JUnit 测试用例获得 InputStream (或其他可读的东西)…?

原文由 carlspring 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.6k
2 个回答

您可以创建自定义附加程序

public class TestAppender extends AppenderBase<LoggingEvent> {
    static List<LoggingEvent> events = new ArrayList<>();

    @Override
    protected void append(LoggingEvent e) {
        events.add(e);
    }
}

并配置 logback-test.xml 以使用它。现在我们可以检查测试中的日志记录事件:

 @Test
public void test() {
    ...
    Assert.assertEquals(1, TestAppender.events.size());
    ...
}

注意:如果没有得到任何输出,请使用 ILoggingEvent 请参阅评论部分了解原因。

原文由 Evgeniy Dorofeev 发布,翻译遵循 CC BY-SA 4.0 许可协议

Slf4j API 不提供这种方式,但 Logback 提供了一个简单的解决方案。

您可以使用 ListAppender :一个白盒 logback appender,其中日志条目添加到 public List 字段中,我们可以使用它来进行断言。

这是一个简单的例子。

Foo 类:

 import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class Foo {

    static final Logger LOGGER = LoggerFactory.getLogger(Foo .class);

    public void doThat() {
        logger.info("start");
        //...
        logger.info("finish");
    }
}

FooTest 类:

 import org.slf4j.LoggerFactory;
import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.Logger;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.read.ListAppender;

public class FooTest {

    @Test
    void doThat() throws Exception {
        // get Logback Logger
        Logger fooLogger = (Logger) LoggerFactory.getLogger(Foo.class);

        // create and start a ListAppender
        ListAppender<ILoggingEvent> listAppender = new ListAppender<>();
        listAppender.start();

        // add the appender to the logger
        fooLogger.addAppender(listAppender);

        // call method under test
        Foo foo = new Foo();
        foo.doThat();

        // JUnit assertions
        List<ILoggingEvent> logsList = listAppender.list;
        assertEquals("start", logsList.get(0)
                                      .getMessage());
        assertEquals(Level.INFO, logsList.get(0)
                                         .getLevel());

        assertEquals("finish", logsList.get(1)
                                       .getMessage());
        assertEquals(Level.INFO, logsList.get(1)
                                         .getLevel());
    }
}

您还可以将匹配器/断言库用作 AssertJ 或 Hamcrest。

使用 AssertJ 它将是:

 import org.assertj.core.api.Assertions;

Assertions.assertThat(listAppender.list)
          .extracting(ILoggingEvent::getFormattedMessage, ILoggingEvent::getLevel)
          .containsExactly(Tuple.tuple("start", Level.INFO), Tuple.tuple("finish", Level.INFO));

原文由 davidxxx 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题