Uploaded image for project: 'Log4j 2'
  1. Log4j 2
  2. LOG4J2-495

As a unit test developer, I want a JUnit rule to handle specific external configuration files.

    XMLWordPrintableJSON

Details

    • Story
    • Status: Closed
    • Minor
    • Resolution: Fixed
    • 2.0-rc1
    • None
    • API, Core
    • None
    • Inside any JUnit test that relies on a specific log4j2.xml file. For example, FileConfigTest in core.

    Description

      There are many unit tests that have the same boilerplate code over and over again:

          private static final String CONFIG = "...";
          private static LoggerContext ctx;
      
          @BeforeClass
          public static void setupClass() {
              System.setProperty(ConfigurationFactory.CONFIGURATION_FILE_PROPERTY, CONFIG);
              ctx = (LoggerContext) LogManager.getContext(false);
          }
      
          @AfterClass
          public static void cleanupClass() {
              System.clearProperty(ConfigurationFactory.CONFIGURATION_FILE_PROPERTY);
              ctx.reconfigure();
              StatusLogger.getLogger().reset();
          }
      

      This sort of pattern can be replaced with a quick implementation of org.junit.rules.ExternalResource like so:

      package org.apache.logging.log4j.test.rule;
      
      import org.apache.logging.log4j.LogManager;
      import org.apache.logging.log4j.core.LoggerContext;
      import org.apache.logging.log4j.core.config.ConfigurationFactory;
      import org.apache.logging.log4j.status.StatusLogger;
      import org.junit.rules.ExternalResource;
      
      public class ExternalConfig extends ExternalResource {
          private final String configFileName;
          private LoggerContext ctx;
      
          public ExternalConfig(String configFileName) {
              this.configFileName = configFileName;
          }
      
          @Override
          protected void before() throws Throwable {
              System.setProperty(ConfigurationFactory.CONFIGURATION_FILE_PROPERTY, this.configFileName);
              this.ctx = (LoggerContext) LogManager.getContext(false);
          }
      
          @Override
          protected void after() {
              System.clearProperty(ConfigurationFactory.CONFIGURATION_FILE_PROPERTY);
              this.ctx.reconfigure();
              StatusLogger.getLogger().reset();
          }
      
          public LoggerContext getContext() {
              return this.ctx;
          }
      }
      

      Now, instead of a class using the same @BeforeClass and @AfterClass template, it can use something like the following:

          private static final String CONFIG = "...";
      
          @ClassRule
          public static ExternalConfig config = new ExternalConfig(CONFIG);
      

      This helps reduce a lot of repeated code. I'll submit a patch that cleans up the unit tests with this in a little while.

      Attachments

        Activity

          People

            mattsicker Matt Sicker
            mattsicker Matt Sicker
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved: