Michael Ekstrand
Michael Ekstrand

Reputation: 29090

How can I have a Maven dependency on the runtime classpath but not the test classpath?

I have a case where I want a dependency on the runtime classpath but not the test classpath. The dependency in question is Logback, an SLF4J implementation. In runtime, I want my code to (optionally) depend on logback so that it has a logging infrastructure available. At test time, however, I want to use the slf4j-nop implementation to black-hole the log output. With logback as a runtime dependency and slf4j-nop as a test dependency, I get a multiple implementation warning from SLF4J when running my tests. I do not see a way to exclude logback from the test classpath.

I do not want to split my tests into a separate package if it can be avoided.

Ideas?

Upvotes: 18

Views: 7149

Answers (4)

Michael Ekstrand
Michael Ekstrand

Reputation: 29090

I've finally found a real solution to this. Since version 2.6 of the Maven Surefire plugin, there is now a classpathDependencyExcludes configuration element that allows specific dependencies to be excluded from the classpath. This therefore works:

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-surefire-plugin</artifactId>
  <version>2.8</version>
  <configuration>
    <classpathDependencyExcludes>
      <classpathDependencyExclude>ch.qos.logback:logback-classic</classpathDependencyExclude>
    </classpathDependencyExcludes>
  </configuration>
</plugin>

Upvotes: 19

Robert Munteanu
Robert Munteanu

Reputation: 68268

If disabling log output is what you want, add a logback configuration file to src/test/resources which discards all output.

If you need to do this for multiple modules in the same reactor build, consider using the maven remote resources plugin.

This plugin is used to retrieve JARs of resources from remote repositories, processes those resources, and incorporate them into JARs you build with Maven. A very common use-case is the need to package certain resources in a consistent way across your organization.

Upvotes: 2

Reboot
Reboot

Reputation: 1744

As far as i know you don't have to exclude it from the test classpath. Maven should keep the order of dependencies in the classpath. If you put your test dependency before the runtime dependency in the dependencies it should also be first in the classpath and a ClassLoader should find the classes in the test dependency first when 2 dependencies contain the same classes. So slf4j would then find the static binding of slf4j-nop and not the logback binding.

Upvotes: 1

Will Gorman
Will Gorman

Reputation: 879

Would it work to add a dependency exclusion on logback from the slf4j-nop test-scoped dependency? Something like

<dependency>
  <groupId>foo</groupId>
  <artifactId>slf4j-nop</artifactId>
  <version>1.0</version>
  <scope>test</scope>
  <exclusions>
    <exclusion>  
      <groupId>foo</groupId>
      <artifactId>logback</artifactId>
    </exclusion>
  </exclusions> 
</dependency>

Upvotes: 0

Related Questions