org.apache.commons.discovery.DiscoveryException: No implementation defined for org.apache.commons.logging.LogFactory
The root cause is that commons-logging depends on Commons Discovery which plays tricks with the class-loader to 'discover' the logging implementation to use at runtime. For an exhaustive list of reasons as to why this is wrong-headed, read this article by Ceki Gülcü.
The normal way to specify which implementation to use is to have a commons-logging.properties file in the classpath with entries something like this:
org.apache.commons.logging.Log = org.apache.commons.logging.impl.Log4JLogger
org.apache.commons.logging.LogFactory = org.apache.commons.logging.impl.LogFactoryImpl
or to specify these as system properties using the -D option when running your app. In my case, I could not (easily) modify the ant targets to change the classpath because Configuration Management maintains shared build scripts that have to go through a heavy process to make any changes. To get around this, I set the system properties in code inside the test:
@BeforeClass
public static void beforeClass() {
System.setProperty("org.apache.commons.logging.Log", "org.apache.commons.logging.impl.Log4JLogger");
System.setProperty("org.apache.commons.logging.LogFactory", "org.apache.commons.logging.impl.LogFactoryImpl");
}
This fixed the issue and the tests now run under CruiseControl.