创建测试规则:
import ch.qos.logback.classic.Logger;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.read.ListAppender;
import org.junit.rules.TestRule;
import org.junit.runner.Description;
import org.junit.runners.model.Statement;
import org.slf4j.LoggerFactory;
import java.util.List;
import java.util.stream.Collectors;
public class LoggerRule implements TestRule {
private final ListAppender<ILoggingEvent> listAppender = new ListAppender<>();
private final Logger logger = (Logger) LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME);
@Override
public Statement apply(Statement base, Description description) {
return new Statement() {
@Override
public void evaluate() throws Throwable {
setup();
base.evaluate();
teardown();
}
};
}
private void setup() {
logger.addAppender(listAppender);
listAppender.start();
}
private void teardown() {
listAppender.stop();
listAppender.list.clear();
logger.detachAppender(listAppender);
}
public List<String> getMessages() {
return listAppender.list.stream().map(e -> e.getMessage()).collect(Collectors.toList());
}
public List<String> getFormattedMessages() {
return listAppender.list.stream().map(e -> e.getFormattedMessage()).collect(Collectors.toList());
}
}
然后使用它:
@Rule
public final LoggerRule loggerRule = new LoggerRule();
@Test
public void yourTest() {
// ...
assertThat(loggerRule.getFormattedMessages().size()).isEqualTo(2);
}
----- JUnit 5 及扩展 2021 年 10 月 -----
日志捕获:
import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.filter.LevelFilter;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.classic.spi.LoggingEvent;
import ch.qos.logback.core.filter.Filter;
import ch.qos.logback.core.read.ListAppender;
import ch.qos.logback.core.spi.FilterReply;
import java.util.List;
import java.util.stream.Collectors;
public class LogCapture {
private ListAppender<ILoggingEvent> listAppender = new ListAppender<>();
LogCapture() {
}
public String getFirstFormattedMessage() {
return getFormattedMessageAt(0);
}
public String getLastFormattedMessage() {
return getFormattedMessageAt(listAppender.list.size() - 1);
}
public String getFormattedMessageAt(int index) {
return getLoggingEventAt(index).getFormattedMessage();
}
public LoggingEvent getLoggingEvent() {
return getLoggingEventAt(0);
}
public LoggingEvent getLoggingEventAt(int index) {
return (LoggingEvent) listAppender.list.get(index);
}
public List<LoggingEvent> getLoggingEvents() {
return listAppender.list.stream().map(e -> (LoggingEvent) e).collect(Collectors.toList());
}
public void setLogFilter(Level logLevel) {
listAppender.clearAllFilters();
listAppender.addFilter(buildLevelFilter(logLevel));
}
public void clear() {
listAppender.list.clear();
}
void start() {
setLogFilter(Level.INFO);
listAppender.start();
}
void stop() {
if (listAppender == null) {
return;
}
listAppender.stop();
listAppender.list.clear();
listAppender = null;
}
ListAppender<ILoggingEvent> getListAppender() {
return listAppender;
}
private Filter<ILoggingEvent> buildLevelFilter(Level logLevel) {
LevelFilter levelFilter = new LevelFilter();
levelFilter.setLevel(logLevel);
levelFilter.setOnMismatch(FilterReply.DENY);
levelFilter.start();
return levelFilter;
}
}
日志捕获扩展:
import ch.qos.logback.classic.Logger;
import org.junit.jupiter.api.extension.AfterTestExecutionCallback;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.jupiter.api.extension.ParameterContext;
import org.junit.jupiter.api.extension.ParameterResolver;
import org.slf4j.LoggerFactory;
public class LogCaptureExtension implements ParameterResolver, AfterTestExecutionCallback {
private Logger logger = (Logger) LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME);
private LogCapture logCapture;
@Override
public boolean supportsParameter(ParameterContext parameterContext, ExtensionContext extensionContext) {
return parameterContext.getParameter().getType() == LogCapture.class;
}
@Override
public Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) {
logCapture = new LogCapture();
setup();
return logCapture;
}
@Override
public void afterTestExecution(ExtensionContext context) {
teardown();
}
private void setup() {
logger.addAppender(logCapture.getListAppender());
logCapture.start();
}
private void teardown() {
if (logCapture == null || logger == null) {
return;
}
logger.detachAndStopAllAppenders();
logCapture.stop();
}
}
然后使用它:
@ExtendWith(LogCaptureExtension.class)
public class SomeTest {
@Test
public void sometest(LogCapture logCapture) {
// do test here
assertThat(logCapture.getLoggingEvents()).isEmpty();
}
// ...
}