在不使用Log4J的情况下测试由Slf4j创建的日志消息

问题描述 投票:1回答:1

我想测试一个方法是否正在创建正确的日志。我的班级看起来像这样:

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.Marker;
import org.slf4j.MarkerFactory;

class EventLogHandler {
    private final Logger logger = LoggerFactory.getLogger(EventLogHandler.class);
    private final Marker eventMarker = MarkerFactory.getMarker("EVENT");

    public void handle(final Event event) {
        final String log = SomeOtherClass.createLog(event);
        logger.info(eventMarker, log);
    }
}

我已经看到了一些用于测试日志的示例/解决方案,但所有这些都使用Log4j,我们在项目中没有使用它。我只能使用Spring-boot,Slf4j和Logback经典的Log4j2。如何使用现有依赖项测试该handle(...)方法?

java unit-testing junit logback slf4j
1个回答
1
投票

使用当前实现,您无法在不使用日志记录系统的情况下测试/验证logger上的调用,并在其输出上断言,例如引入logback并使用stdout appender对其进行配置并捕获stdout并对其进行断言等。

为了测试你的课程而不做任何一项,你必须得到你在logger使用的EventLogHandler实例。通过像这样构建logger,当前的实现使这很困难:

private final Logger logger = LoggerFactory.getLogger(EventLogHandler.class);

在这种情况下测试的常用方法是重构logger的创建,以便在运行测试时将模拟的实例注入EventLogHandler。例如:

class EventLogHandler {
    private final Marker eventMarker = MarkerFactory.getMarker("EVENT");
    private final Logger logger;

    public EventLogHandler() {
        this(LoggerFactory.getLogger(EventLogHandler.class));
    }

    // probably only used by your test case
    public EventLogHandler(Logger logger) {
        this.logger = logger;
    }

    public void handle(final Event event) {
        logger.info(eventMarker, log);
    }
}

然后像这样测试:

@Test
public void someTest() {
    Logger logger = Mockito.mock(Logger.class);
    EventLogHandler sut = new EventLogHandler(logger);

    sut.handle(event);

    // verify that the right state is extracted from the given event and that the correct marker is used
    Mockito.verify(logger).info(..., ...);
}

一个不太常见的替代方法是使用Powermock来模拟这个调用:LoggerFactory.getLogger(EventLogHandler.class);然后使用Mockito验证对它的调用,方法与上面显示的相同。

© www.soinside.com 2019 - 2024. All rights reserved.