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

时间:2019-04-15 15:10:02

标签: java unit-testing junit logback slf4j

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

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的Log4j2,Slf4j和Logback classic。 如何使用现有依赖项测试该handle(...)方法?

1 个答案:

答案 0 :(得分:1)

在当前的实现中,如果不使用日志记录系统并断言其输出,例如,则无法测试/验证logger上的调用。引入logback并使用stdout附加程序对其进行配置,并捕获stdout并对其进行断言等。

为了测试您的类而不进行任何操作,您必须动手使用logger中使用的EventLogHandler实例。当前的实现方式通过像这样构造logger使得这一点变得困难:

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

在这种情况下,一种常见的测试方法是重构记录器的创建方式,以便在运行测试时可以将模拟的实例注入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以与上面所示相同的方式来验证对其的调用。