Comprehensive test suite and testing utilities for Apache Log4j core logging implementation
—
Comprehensive JUnit 4 and JUnit 5 integration for Log4j testing, providing TestRules, Extensions, and annotations for LoggerContext management, configuration loading, and test lifecycle integration.
JUnit 4 TestRule for constructing LoggerContext with specified configuration files and managing test lifecycle.
/**
* JUnit 4 TestRule for LoggerContext management
* Implements TestRule and LoggerContextAccessor
*/
public class LoggerContextRule implements TestRule, LoggerContextAccessor {
/**
* Constructor for creating rule with configuration file
* @param configLocation Configuration file path relative to classpath
*/
public LoggerContextRule(String configLocation);
/**
* Retrieves typed appender by name
* @param name The appender name
* @return The appender instance or null if not found
*/
public <T extends Appender> T getAppender(String name);
/**
* Retrieves required typed appender, throws if not found
* @param name The appender name
* @param cls The expected appender class
* @return The appender instance
* @throws AssertionError if appender not found or wrong type
*/
public <T extends Appender> T getRequiredAppender(String name, Class<T> cls);
/**
* Convenience method for getting ListAppender
* @param name The appender name
* @return The ListAppender instance
*/
public ListAppender getListAppender(String name);
/**
* Gets logger with default name (test class name)
* @return Logger instance
*/
public Logger getLogger();
/**
* Gets logger for specified class
* @param cls The class to get logger for
* @return Logger instance
*/
public Logger getLogger(Class<?> cls);
/**
* Gets logger with specified name
* @param name The logger name
* @return Logger instance
*/
public Logger getLogger(String name);
/**
* Gets the current configuration
* @return Configuration instance
*/
public Configuration getConfiguration();
/**
* Gets the LoggerContext
* @return LoggerContext instance
*/
public LoggerContext getLoggerContext();
/**
* Triggers reconfiguration of the logging system
*/
public void reconfigure();
/**
* Creates RuleChain with file cleanup rules
* @param files Files to clean up after test
* @return RuleChain for combining rules
*/
public RuleChain withCleanFilesRule(String... files);
/**
* Creates RuleChain with folder cleanup rules
* @param folders Folders to clean up after test
* @return RuleChain for combining rules
*/
public RuleChain withCleanFoldersRule(String... folders);
}Usage Examples:
import org.apache.logging.log4j.core.test.junit.LoggerContextRule;
import org.apache.logging.log4j.core.test.appender.ListAppender;
import org.junit.Rule;
import org.junit.Test;
public class JUnit4LoggerTest {
@Rule
public LoggerContextRule context = new LoggerContextRule("log4j2-test.xml");
@Test
public void testBasicLogging() {
Logger logger = context.getLogger();
ListAppender appender = context.getListAppender("TestAppender");
logger.info("Test message");
assertEquals(1, appender.getEvents().size());
assertEquals("Test message", appender.getMessages().get(0));
}
@Test
public void testWithCleanup() {
// Use rule chain for automatic cleanup
}
}
// With cleanup rules
public class FileCleanupTest {
@Rule
public RuleChain rules = new LoggerContextRule("log4j2-file-test.xml")
.withCleanFilesRule("test.log", "test.log.1")
.withCleanFoldersRule("logs");
@Test
public void testFileLogging() {
// Files will be automatically cleaned up after test
}
}JUnit 5 annotation for specifying configuration files and lifecycle management.
/**
* JUnit 5 annotation for specifying LoggerContext configuration
*/
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface LoggerContextSource {
/**
* Configuration file name relative to classpath
* @return Configuration file path
*/
String value();
/**
* When to reconfigure the logging system
* @return ReconfigurationPolicy enum value
*/
ReconfigurationPolicy reconfigure() default ReconfigurationPolicy.NEVER;
/**
* Shutdown timeout value
* @return Timeout value
*/
long timeout() default 0;
/**
* Shutdown timeout unit
* @return TimeUnit for timeout
*/
TimeUnit unit() default TimeUnit.SECONDS;
}Annotation for specifying names of configuration items to inject into JUnit 5 test parameters.
/**
* Specifies name of Appender to inject into JUnit 5 tests
*/
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface Named {
/**
* Name of configuration item to inject
* @return The name string
*/
String value();
}Enum indicating when to reconfigure the logging system during tests.
/**
* Indicates when to reconfigure logging system during tests
*/
public enum ReconfigurationPolicy {
/** Never reconfigure during test lifecycle */
NEVER,
/** Reconfigure before each test method */
BEFORE_EACH,
/** Reconfigure after each test method */
AFTER_EACH
}JUnit 5 Usage Examples:
import org.apache.logging.log4j.core.test.junit.LoggerContextSource;
import org.apache.logging.log4j.core.test.junit.Named;
import org.apache.logging.log4j.core.test.appender.ListAppender;
import org.junit.jupiter.api.Test;
@LoggerContextSource("log4j2-test.xml")
public class JUnit5LoggerTest {
@Test
public void testWithInjectedAppender(@Named("TestAppender") ListAppender appender,
Logger logger) {
logger.info("Test message");
assertEquals(1, appender.getEvents().size());
assertEquals("Test message", appender.getMessages().get(0));
}
@Test
@LoggerContextSource(value = "log4j2-method-test.xml",
reconfigure = ReconfigurationPolicy.BEFORE_EACH)
public void testWithMethodConfig(@Named("MethodAppender") ListAppender appender) {
// Uses method-specific configuration
}
}Supporting TestRules for various testing scenarios.
/**
* TestRule for cleaning up external files after tests
*/
public class CleanFiles extends AbstractExternalFileCleaner implements TestRule {
/**
* Creates rule for cleaning specified files
* @param files Files to clean up
* @return CleanFiles rule instance
*/
public static CleanFiles cleanFiles(String... files);
}
/**
* TestRule for cleaning up external folders after tests
*/
public class CleanFolders extends AbstractExternalFileCleaner implements TestRule {
/**
* Creates rule for cleaning specified folders
* @param folders Folders to clean up
* @return CleanFolders rule instance
*/
public static CleanFolders cleanFolders(String... folders);
}
/**
* TestRule for JDBC testing setup and teardown
*/
public class JdbcRule implements TestRule {
/**
* Creates JDBC rule with connection string and setup SQL
* @param connectionString JDBC connection string
* @param setupSql SQL to execute for setup
* @return JdbcRule instance
*/
public static JdbcRule createRule(String connectionString, String setupSql);
}
/**
* TestRule for JNDI testing setup
*/
public class JndiRule implements TestRule {
/**
* Creates JNDI rule for testing JNDI-based configurations
* @return JndiRule instance
*/
public static JndiRule createRule();
}
/**
* TestRule for URL stream handler testing
*/
public class URLStreamHandlerFactoryRule implements TestRule {
/**
* Creates rule for custom URL stream handlers
* @param factory URL stream handler factory
* @return URLStreamHandlerFactoryRule instance
*/
public static URLStreamHandlerFactoryRule create(URLStreamHandlerFactory factory);
}JUnit 5 tags and categories for test organization.
/**
* Container for JUnit 5 tags
*/
public final class Tags {
/**
* Tag for async logger tests requiring LMAX Disruptor
*/
public static final String ASYNC_LOGGERS = "async-loggers";
}
/**
* Property lookup for testing scenarios
*/
public class TestPropertyLookup extends AbstractLookup {
/**
* Looks up test-specific properties
* @param event The log event
* @param key The property key
* @return The property value or null
*/
public String lookup(LogEvent event, String key);
}public class MyLoggerTest {
@Rule
public LoggerContextRule context = new LoggerContextRule("test-config.xml");
@Test
public void testLogging() {
Logger logger = context.getLogger();
ListAppender appender = context.getListAppender("TestList");
logger.error("Error message");
assertEquals(1, appender.getEvents().size());
assertEquals(Level.ERROR, appender.getEvents().get(0).getLevel());
}
}@LoggerContextSource("test-config.xml")
class MyLoggerTest {
@Test
void testLogging(@Named("TestList") ListAppender appender, Logger logger) {
logger.error("Error message");
assertEquals(1, appender.getEvents().size());
}
}@Rule
public RuleChain rules = RuleChain
.outerRule(new JndiRule())
.around(new LoggerContextRule("jndi-config.xml"))
.around(CleanFiles.cleanFiles("test.log"));Install with Tessl CLI
npx tessl i tessl/maven-org-apache-logging-log4j--log4j-core-test