Details
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.