使用 Commons 日志记录和 Log4j 2.0 增强代码覆盖率

Enhanced code coverage with Commons logging and Log4j 2.0

我目前正在从 Log4j 1.2 迁移到 Log4j 2。 我们使用 Apache Commons Logging 1.1 (JCL),以 Log4j2 作为实现。

现在执行单元测试时,像

这样的语句
 if (log.isInfoEnabled()) {
   log.info("example");
 }

如果日志日志级别太高(例如,此 examole 中的 WARN),将在覆盖率报告中显示为未覆盖的行,因为 if 正文将不会被执行。

在 Log4j 1 中,我公司的某个人因此编写了一个自定义记录器,如果它检测到它是来自 Maven Surefire 的 运行,那么对于所有 log.isXXXEnabled() 方法,它将 return 为真,就像这样:

import org.apache.commons.logging.Log;
import org.apache.commons.logging.impl.Log4JLogger;

public class Log4JEnhancedCoverage implements Log {

  private static final long serialVersionUID = -8715529047111858959L;

  private final Log logger;

  private final boolean mavenRun;

  public LogEnhancedCoverage(String name) {
    this.logger = new Log4JLogger(_name);
    this.mavenRun = TestsRunContext.isMavenSurefireRun();
  }

  @Override
  public boolean isTraceEnabled() {
    return (mavenRun) ? true : logger.isTraceEnabled();
  }

  @Override
  public void trace(Object message) {
   logger.trace(message);
  }

  // repeat for warn, info, etc
}

效果是每个isXXXEnabled()块被执行,日志语句通过配置文件重定向到log4j。 Log4j 本身将看到仅显示指定日志级别的消息,而执行 all 级别的代码块。 旧:问题是如您所见,Log4j 记录器实现是直接从 JCL 的 impl 包中实例化的。 (是的,他们发布了自己的适配器实现!)。

在我的新设置中,我使用的是 log4j-jcl 工件,但我不知道如何在构造函数中正确创建 Log4j 2 兼容记录器。

更新: log4j-jcl 附带了自己的日志工厂,它加载了 log4j 2 特定的记录器实现。因此,特定记录器的 commons-logging 配置根本不被接受。

只需使用公共日志记录器 API 获取记录器,而不是直接实例化它,就可以了。

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
//REMOVE THIS: import org.apache.commons.logging.impl.Log4JLogger;

public class Log4JEnhancedCoverage implements Log {

    private static final long serialVersionUID = -8715529047111858959L;

    private final Log logger;

    private final boolean mavenRun;

    public Log4JEnhancedCoverage(String name) {
        //REMOVE THIS: this.logger = new Log4JLogger(name);
        this.logger = LogFactory.getLog(name);
        ...