gpt4 book ai didi

unit-testing - 对 SLF4J 日志消息进行单元测试的最佳方法是什么?

转载 作者:行者123 更新时间:2023-12-03 07:34:45 25 4
gpt4 key购买 nike

我正在使用 slf4j,我想对我的代码进行单元测试,以确保在某些条件下生成警告/错误日志消息。我希望这些是严格的单元测试,所以我不想从文件中提取日志配置来测试是否生成日志消息。我使用的模拟框架是 Mockito。

最佳答案

创建测试规则:

    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();
}

// ...
}

关于unit-testing - 对 SLF4J 日志消息进行单元测试的最佳方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4650222/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com