Log4J Configuration Not Loading Properly With maven-surefire-plugin
Today, I had a strange problem with maven, the maven surefire plugin and log4j.xml configuration not really getting into the action. No matter what I did, I could not get log4j logging statements lower than WARN level to show on stdout. But only when the tests ran from maven surefire! If I executed them directly from inside IDEA (with an IDEA project imported from the maven POMs), it worked like a charm. I think I did all the correct things:
- I had log4j in my dependencies (even tried scope test)
- I had log4j.xml in src/test/resources and it “compiled” nicely into target/test-classes
- I tried putting log4j as a dependency on the surefire-plugin too, but that made things worse (class identity problems, as some log4j classes were loading from another class loader)
- When setting the system property log4j.debug=true, I could see my log4j.xml file load properly
I Found Out Something
After a lot of trying and debugging, I noticed that we had some extra setup in our top-level POM on the surefire plugin. Among other things, we had forkMode set to pertest. Okay, that might be it. So I tried setting forking to never, and bam, things started working. Apparently, the log4j.xml configuration I saw loading properly was loaded before the forking, but when forked, it never loaded. Hmmmm. Strange, because log4j was on the classpath when the tests ran, or the code would have failed execution.
With this plugin definition in my top-level POM, I got things working again:
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <configuration> <forkMode>pertest</forkMode> <!-- this is what triggers the problem, having it to "never" works also --> <systemProperties> <property> <name>log4j.configuration</name> <value>file:target/test-classes/log4j.xml</value> </property> </systemProperties> </configuration> </plugin>
I am using the log4j.configuration system property, to point directly at the log4j configuration file. This made the config load in the forked unit testing scenario with surefire. So, either use a forkMode of never or use the system property.
What might I have missed, to endure such pain today?