Suppress Log Messages During Unit Tests
Introduction
Goal
Suppress expected or harmless log messages while running unit tests.
Background
When running unit tests, you may want to suppress expected or harmless log messages in order to keep your console output clean. There are two ways to suppress log messages, both having their own use cases:
- Suppress log messages with org.onehippo.testutils.log4j.Log4jInterceptor
- Suppress log messages with org.onehippo.testutils.log4j.StringMatchFilter
To make these classes available in your unit tests, add a dependency on hippo-cms-testutils:
<dependency> <groupId>org.onehippo.cms7</groupId> <artifactId>hippo-cms-testutils</artifactId> <scope>test</scope> </dependency>
Suppress Log Messages with Log4jInterceptor
When you expect some invocation in your unit test to log one or more messages, but don't want these messages to show up in the console in order to keep the output clean, you can suppress these log messages by using Log4jInterceptor. In the following example, assume that the invocation of componentManager.start() triggers an expected log message:
@Test public void myUnitTest() throws Exception { final SpringComponentManager componentManager = .... [...] componentManager.start(); [...] }
You don't want that log message to pollute the unit test's console output, so you want to suppress it on the console. You can do this by wrapping the invocation that logs the warning as follows:
@Test public void myUnitTest() throws Exception { final SpringComponentManager componentManager = .... [...] try (Log4jInterceptor interceptor = Log4jInterceptor.onError() .trap(loggerName1, loggerName2 ... loggerNameN).build()) { componentManager.start(); } [...] }
Next to the onError method used above, you can also use onDebug, onInfo, onWarn and onFatal to adjust the log level of the loggers specified in the var-args list of arguments to the trap method for the execution of the code inside the try-with-resources block.
Suppress Log Messages with StringMatchFilter
In the case where the code producing an expected, harmless log message is buried more deeply in your unit test, you may not be able to suppress that message using Log4jInterceptor. Instead, you may use StringMatchFilter, which is an org.apache.logging.log4j.core.Filter you can add to an Appender in your log4j2.xml configuration in order to suppress log messages. StringMatchFilter is configured through log4j-filters.txt based on a contains criterium.
Example cases where you may want to use StringMatchFilter are:
- Your unit test bootstraps a partial set of content into the repository, producing some warnings.
- Your unit test partially mocks an object, causing some warnings
Use StringMatchFilter as follows:
Step 1
Add StringMatchFilter to the list of filters of the Console Appender in log4j2.xml.
<Appenders> <Console name="console" target="SYSTEM_OUT"> <Filters> <ThresholdFilter level="error"/> <StringMatchFilter/> </Filters> <PatternLayout pattern="%d{dd.MM.yyyy HH:mm:ss} %-5p [%C.%M():%L] %m%n"/> </Console> </Appenders>
Step 2
In the same location as the log4j2.xml file, create a file log4j-filters.txt to list your filter values. Every line that does not start with a # is a filter value. Any log message that contains the text of one of the filter values is suppressed. For example, if the log4j-filters.txt is as follows:
# # Copyright (C) 2020 BloomReach B.V. # Error initializing content for frontend-templatecomposer.xml in '/hippo:configuration/hippo:frontend/cms' Error initializing content for frontend-loader.xml in '/hippo:configuration/hippo:frontend/cms/cms-static' Error initializing content for frontend-cluster.xml in '/hippo:configuration/hippo:frontend/cms'
Then any log message that contains one of the three lines above (not the ones that start with #) is suppressed and not logged to the Console Appender. Thus, for example the message [Error initializing content for frontend-templatecomposer.xml in '/hippo:configuration/hippo:frontend/cms' because of unknown namespace 'hippo:frontend'] will be suppressed.