Changelog
slf4j-test-3.0.3 (2025-08-21)
Fixes:
slf4j-test-3.0.2 (2025-08-20)
Known issues:
- The POM publihed in version
3.0.2(https://repo.maven.apache.org/maven2/com/github/valfirst/slf4j-test/3.0.2/slf4j-test-3.0.2.pom) is broken. Please use version3.0.3
Fixes:
- #596 via #600 Optimize performance: replace
CopyOnWriteArrayListwithCollections.synchronizedListinTestLogger(by @valfirst) - #601 Optimize performance: pass empty array to
Collection#toArraycalls (by @valfirst)
Updates:
- Bump
org.slf4j:slf4j-apifrom2.0.7to2.0.17 - Bump
org.assertj:assertj-corefrom3.24.2to3.27.4
slf4j-test-3.0.1 (2023-07-13)
Fixes:
slf4j-test-3.0.0 (2023-07-11)
Breaking changes
-
#380 via #383 - Switch from Lidalia Level to SLF4J Level (by @karstenspang)
-
uk.org.lidalia.slf4jext.Levelis replaced withorg.slf4j.event.LevelThe
org.slf4j.event.Levelclass has been present in SLF4J since version1.7.15from 2016. There is little reason for a client to use a version older than that.Changing the
importstatement from one package to the other handles most of the changes. But some differences between the twoLevelclasses remain.Ordinal Values
In
uk.org.lidalia.slf4jext.Level,ERRORhas the lowest ordinal value, andTRACEhas the highest. Inorg.slf4j.event.Level, it is the other way round. When comparing levels usingEnum.compareTo, the equality sign will have to be reversed. In SLF4J Test, this is used to decide whether to print the log message.OFFLevelorg.slf4j.event.Levelhas noOFFlevel. This means that another way must be used to specify that printing is off.nullis the only other value you can pass as an enum. The print level logic is changed to usenullas “off”.enableableLevelsuk.org.lidalia.slf4jext.Levelhas the static methodenableableLevelsthat returns the set of enum values corresponding to log levels that can be enabled. Since all values represent enableable levels inorg.slf4j.event.Level,EnumSet.allOf(Level.class)provides the equivalent funtionality. -
Dependency
uk.org.lidalia:lidalia-slf4j-extis dropped
-
-
#380 via #384 - Remove Guava as dependency (by @karstenspang)
-
Guava Collections are replaced with Java Collections
Parameter and return types are changed to be simply
List,Map, orSet, instead of the specific ones from Guava. The client can still pass the Guava ones as parameters if needed. In case the client assign a returned value to a specific type, code changes are needed.Returned vales are wrapped using
java.util.Collections.unmodifiableList/Map/Setafter copying.Internal values are implemented using
ArrayList,HashMap, orHashSetwrapped to be made unmodifiable. As a special case, enabled log level sets are to be represented asEnumSet<Level>. -
Dependency
com.google.guava:guavais dropped
-
-
#312, #380 via #326 - Use java.time's
Instantrather thanjoda-time(by @josephw)org.joda.time.Instantis replaced withjava.time.Instant- Dependency
joda-time:joda-timeis dropped
-
#390 via #394 - Avoid substitution of
nullvalues (by @karstenspang)null-s were replaced by other values:- When a
LoggingEventwas constructed with arguments,null-s were replaced withOption.empty(). If logging events were just compared, such replacement had no impact. So restoration ofnull-s is considered as an internal change here. - If
nullvalue was inserted in the MDC, it was replaced with the string"null". If MDC functionality were tested, such replacement could be annoying. In particular, the assertion failure message showednullin both the expected and the actual value. Now such substitution is eliminated,nullvalue is always used.
- When a
-
#409 via #411 Drop static binders (by @valfirst)
slf4j-api 2.0.x relies on the
ServiceLoadermechanism to find its logging backend. SLF4J 1.7.x and earlier versions relied on the static binder mechanism which is no loger honored by slf4j-api version 2.0.x. SLF4J Test doesn't support SLF4J 1.7.x and 1.8.x since version2.4.0(when breaking changes were introduced in SLf4J API). Thus static binders are removed:org.slf4j.impl.StaticLoggerBinderorg.slf4j.impl.StaticMDCBinderorg.slf4j.impl.StaticMarkerBinder
Implemented enhancements:
-
#398 via #399 Add utility classes to support
java.util.loggingtesting (by @karstenspang)- A helper class to do the
java.util.loggingsetup is added, as well as a JUnit 5 extension that calls it. jul-to-slf4jbridge is added as an optional dependency.
- A helper class to do the
-
#392 via #401 Implement MDC configuration management (by @karstenspang)
There is now configuration for four aspects:
- Whether an MDC is supported at all.
- Whether the MDC is inherited by child threads.
- Whether
getCopyOfContextMap()shall return an empty map ornullif the MDC has not been set. - Whether
nullis a legal value in an MDC entry.nullkeys are never allowed.
-
#407 via #408, #412 Add full support for the SLF4J fluent logging API (by @karstenspang)
LoggingEventclass supports multiple markers. This is allowed by the fluent API.LoggingEventclass stores the key/value pair list that can be generated fluent API.- The new
TestLoggingEventBuilderclass can be used for fluently creatingLoggingEventinstances for use as expected values.
-
#183 via #410 Add ability to configure cleanup stage (by @valfirst)
Now it is possible to configure JUnit 5 stage which cleanup should be performed at using
@TestLoggerFactorySettingsannotation or while programmatic extension registration is performed.
Fixes:
-
#400 via #401 Fix Javadoc links (by @karstenspang)
-
#393 via #405 Do not change the defaults for all threads at resetting enabled logging levels (by @karstenspang)
slf4j-test-2.9.0 (2023-03-22)
Implemented enhancements:
-
#360 - Add ability to make assertions using the
PredicateBuildermore fluent (by @topbadger)Static helper method and method overloads are added to make assertions using the
PredicateBuildermore fluent.This allows assertions to be declared as follows:
assertThat(logger).hasLogged(aLog().withLevel(Level.WARN).withMessage("Something"));as opposed to:
assertThat(logger).hasLogged(new PredicateBuilder().withLevel(Level.WARN).withMessage("Something").build());
Updates:
- Bump
org.slf4j:slf4j-apifrom2.0.6to2.0.7 - Bump
org.assertj:assertj-corefrom3.23.1to3.24.2
slf4j-test-2.8.1 (2023-01-05)
Fixes:
slf4j-test-2.8.0 (2022-12-28)
Implemented enhancements:
-
#188 via #328 - Restructure assertions to be based on predicates (by @topbadger)
By re-structuring the assertion logic to be based upon predicates, the following enhancements have been made:
Custom Predicates
Consumers can now provide custom predicates so that they can assert on
LoggingEvents in specific ways in addition to the ways previously supported by the library.Example:
assertThat(logger) .hasLogged(event -> event.getFormattedMessage().startsWith("First section of long log message"));MDC Comparison Strategy
The MDC comparison strategy can now be set by consumers.
- The full MDC context isn't always relevant to the test, yet the assertions previously enforced this check. The result was that people were unable to use the fluent assertions we provide in a number of scenarios.
- The previous behaviour of requiring the MDC contents to match exactly has been retained as the default.
Example:
assertThat(logger) .usingMdcComparator(MdcComparator.IGNORING) .hasLogged(warn("Some log message"));Enhanced Assertion Failure Messages
Assertion failure messages have been enhanced to show the list of
LoggingEvents that were actually captured to make debugging the cause of the failure easier.Example:
Failed to find event: LoggingEvent{level=ERROR, mdc={}, marker=Optional.empty, throwable=Optional[throwable], message='There was a problem!', arguments=[]} The logger contained the following events: - LoggingEvent{level=WARN, mdc={}, marker=Optional.empty, throwable=Optional.empty, message='Some other problem', arguments=[]} - LoggingEvent{level=ERROR, mdc={}, marker=Optional.empty, throwable=Optional.empty, message='Yet another problem', arguments=[]}
slf4j-test-2.7.0 (2022-12-19)
Implemented enhancements:
-
#314 via #324 - Introduce a new
capture.levelproperty and API to control captured events globally (by [@youribonnaffe]https://github.com/youribonnaffe)Introduce a new global setting
capture.levelto disable storing (and printing) logs at a given level (following the level hierarchy).The implementation is very similar to the
print.levelglobal setting.This is useful when tests are generating a lot of logging events that are not of interest and don't need to be captured. ArchUnit tests are known to be such tests and can be quite slow when
slf4j-testis used.
Updates:
- Bump
org.slf4j:slf4j-apifrom2.0.0-alpha7to2.0.6 - Bump
joda-time:joda-timefrom2.10.14to2.12.2 - Bump
org.assertj:assertj-corefrom3.22.0to3.23.1
slf4j-test-2.6.1 (2022-04-01)
Fixes:
- #255 via #257 Fix memory leak when clearing logs in all threads (by @sofiamorseletto)
Going back to the custom
ThreadLocalimplementation (uk.org.lidalia.lang.ThreadLocal) in order to prevent memory leaks.
slf4j-test-2.6.0 (2022-03-21)
Implemented enhancements:
-
#247 Log events found when AssertJ assertion fails (by @jamietanna)
This helps quite a bit with diagnosing why an assertion fails, as the alternative is to either attach a debugger or
System.out.printlnthe logging events found. -
#250 via #251 Add TCCL attribute to
LoggingEvent(by @sofiamorseletto)The changes add an attribute on
LoggingEventwhich contains the Thread Context Classloader used when the logging event was created. This allows the assertion of the TCCL of a certain log to check that the log was handled by the correct classloader.
Updates:
- Bump
org.slf4j:slf4j-apifrom2.0.0-alpha6to2.0.0-alpha7 - Bump
com.google.guava:guavafrom31.0.1-jreto31.1-jre - Bump
joda-time:joda-timefrom2.10.13to2.10.14
slf4j-test-2.5.0 (2022-02-08)
Updates:
-
#228 - Bump
org.slf4j:slf4j-apifrom2.0.0-alpha5to2.0.0-alpha6NOTE:
slf4j-test:2.5.0is compatible withslf4j-api:2.0.0-alpha6and higher and it is not compatible with previous versions (see compatibility matrix for more details). The root cause is breaking changes in SLF4J API: -
Bump
org.assertj:assertj-corefrom3.21.0to3.22.0
slf4j-test-2.4.1 (2021-12-23)
Implemented enhancements:
-
#207 - Enable assertions to be made on LoggingEvents from any thread (by @topbadger)
The current implementation only verifies against the
LoggingEvents captured by the thread that is running the test.TestLoggerprovides access to all events captured across any thread viaTestLogger::getAllLoggingEvents()so a modifying method has been added to the assertion class to allow the assertion mode to be switched.Example usage:
assertThat(logger).anyThread().hasLogged(...); -
#220 via #221 - Format
null-s inLoggingEvent#getFormattedMessage()the same way asSLF4J(by @josephw)LoggingEvent#getFormattedMessage()is public (#23). However, it hasn't presentednullvalues the same way as SLF4J, due to un-matched wrapping/unwrapping ofOptional:LoggingEvent e = new LoggingEvent(Level.INFO, "Content: {}, {}", null, "value"); System.out.println(e.getFormattedMessage());Produced previously:
Content: Optional.empty, valueProduces now:
Content: null, value
Updates:
- Bump
org.slf4j:slf4j-apifrom2.0.0-alpha4to2.0.0-alpha5 - Bump
joda-time:joda-timefrom2.10.10to2.10.13 - Bump
com.google.guava:guavafrom30.1.1-jreto31.0.1-jre - Bump
org.assertj:assertj-corefrom3.20.2to3.21.0
slf4j-test-2.4.0 (2021-08-25)
Updates:
-
#190 - Bump
org.slf4j:slf4j-apifrom2.0.0-alpha2to2.0.0-alpha4 -
#190 - Update according to the changes in SLF4J API
2.0.0-alpha3NOTE:
slf4j-test:2.4.0is compatible withslf4j-api:2.0.0-alpha3and higher and it is not compatible with previous versions (see compatibility matrix for more details). The root cause is breaking change in SLF4J API.
slf4j-test-2.3.0 (2021-08-05)
Implemented enhancements:
- #184 - Add assertion for substrings of log messages (by @jamietanna)
- #187 - Add assertions based on
LoggingEvent(by @jamietanna)
Internals:
- #185 via #186 Enforce consistent code style (by @jamietanna)
slf4j-test-2.2.0 (2021-07-29)
Implemented enhancements:
- #181 via #182 - Add initial AssertJ assertions (by @jamietanna)
Updates:
- #124 via #126 - Add an explicit license to the project
- Bump
org.slf4j:slf4j-apifrom 1.8.0-beta2 to 2.0.0-alpha2 - Bump
joda-time:joda-timefrom 2.10 to 2.10.10 - Bump
com.google.guava:guavafrom 26.0-jre to 30.1.1-jre
slf4j-test-2.1.1 (2018-09-17)
Implemented enhancements:
- Make LoggingEvent self-descriptive: implement
toStringmethod (by @valfirst)
Updates:
- Bump
com.google.guava:guavafrom 25.1-jre to 26.0-jre
slf4j-test-2.1.0 (2018-06-29)
Implemented enhancements:
- #23 - Make LoggingEvent#getFormattedMessage public (by @valfirst)
- Drop
uk.org.lidalia:lidalia-langdependency (by @valfirst)
Updates:
- Bump
org.slf4j:slf4j-apifrom 1.8.0-beta1 to 1.8.0-beta2 - Bump
joda-time:joda-timefrom 2.9.9 to 2.10 - Bump
com.google.guava:guavafrom 24.1-jre to 25.1-jre
slf4j-test-2.0.0 (2018-03-19)
Breaking changes
- Increase minimum required JDK version from 7 to 8
- Change base package to
com.github.valfirstto reflect ownership
Implemented enhancements:
- #6 - Implement JUnit 5 support (by @valfirst)
- Optimize performance: replace CopyOnWriteArrayList with Collections.synchronizedList in
TestLoggerFactory(by @valfirst)
Updates:
- Bump
org.slf4j:slf4j-apifrom 1.8.0-beta0 to 1.8.0-beta2 - Bump
com.google.guava:guavafrom 20.0 to 24.1-jre
slf4j-test-1.3.0 (2018-01-05)
groupId was changed to com.github.valfirst to reflect ownership
Implemented enhancements:
- Support new SLF4J binding mechanism introduced in SLF4J 1.8
Updates:
- Upgrade to Guava 20.0, Joda Time 2.9.9
Version 1.2.0
Allows construction of standalone instances to facilitate logging in different contexts.
Version 1.1.0
Fixes https://github.com/Mahoney/slf4j-test/issues/4 - Detect throwable as last varargs element if the format string has n-1 parameters.
With thanks to https://github.com/philipa
Version 1.0.1
Fixed an issue where null arguments to a logging event and null values in the MDC caused a NullPointerException due to Guava's strict attitude to nulls. Null arguments now appear as Optional.absent() and null values in the MDC as the String “null”.
