我想测试一个方法是否正在创建正确的日志。我的班级看起来像这样:
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(...)方法?
使用当前实现,您无法在不使用日志记录系统的情况下测试/验证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验证对它的调用,方法与上面显示的相同。