15

I have project that depends on commons-httpclient [2.0] (compile).

I would like to write some jbehave tests - jbehave-core 3.4.5 (test). Both this dependencies depend on commons-lang but in different versions - 1.0.1 and 2.5.

dependency

When I execute mvn package I get [BUID FAILURE] in tests section. There is an exception for my testcase in surefire-plugin output:

java.lang.NoSuchMethodError: org.apache.commons.lang.StringUtils.substringBeforeLast(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;

As I looked in source code - in commons-lang 1.0.1 - indeed, there is no StringUtils.substringBeforeLast(...) method. Why maven uses commons-lang from commons-httpclient (compile) and not from jbehave-core in testing?

I can't afford to exclude this conflicting dependency in commons-httpclient so it must stay in compile time.

So how can this be resolved - commons-lang 2.5 version in testing and 1.0.1 in compile time?

cb4
  • 6,689
  • 7
  • 45
  • 57
Xeon
  • 5,949
  • 5
  • 31
  • 52

4 Answers4

12

Maven 3:

Maven 3 will attempt to obtain the nearest dependency, effectively ensuring that only one of the compile or test scoped dependency is used for both the compile and test phases.

(Thanks Vineet Reynolds)

Maven 2 (OLD):

try to define 2 different <dependency> tags with different versions and scopes. Use tag <scope>test</scope> inside dependency for tests and <scope>compile</scope> for compilation.

Gaël J
  • 11,274
  • 4
  • 17
  • 32
AlexR
  • 114,158
  • 16
  • 130
  • 208
  • It worked! Thanks. In m2eclipse plugin I have '(ommited for conflict witch 2.5) [compile]' in commons-httpclient subcategory but this is probably m2eclipse problem – Xeon Jul 04 '11 at 20:48
  • This doesn't work for me, and I don't know why - http://stackoverflow.com/questions/9364511/maven-different-dependency-version-in-test – DeejUK Feb 20 '12 at 16:22
  • 23
    A friendly warning - this is no longer valid for Maven 3 (used to be valid for Maven 2). Maven 3 will attempt to obtain the nearest dependency, effectively ensuring that only one of the compile or test scoped dependency is used for both the compile and test phases. – Vineet Reynolds Dec 03 '13 at 11:17
  • 3
    @VineetReynolds So how could the problem with incompatible versions be resolved using Maven 3? – Stefan Haberl Sep 05 '14 at 11:17
  • 2
    @StefanHaberl you could try to move test to separate maven module and add there different dependency version / scope. – Przemek Nowak Sep 24 '14 at 09:11
  • @przemek Separate modules would make life hard for me, especially when you use QS tools like sonar or code coverage tools like cobertura - getting the figures right if you use different modules for main/test is a pain – Stefan Haberl Sep 24 '14 at 09:48
  • 1
    @StefanHaberl I have dependency for servlets 3.0.1 with scope test and transition dependency for servlets 2.5 with compile scope and it works for me. I'm using the Spring4 with MVC test but the application runs on the tomcat 6. It's a little weird but it works. With direct dependency I had the same problem as you. If you want I could add the new answer with details (generally I noticed when I changed servlets to 3.0.1 that one of my libraries with artifactId ziplet use the servlet 2.5). – Przemek Nowak Oct 13 '14 at 18:53
4

In Maven 3, you can trick maven by adding a dot after groupId

<dependency>
  <groupId>groupId.</groupId>
  <artifactId>artifactId</artifactId>
  <version>version1</version>
  <scope>test</scope>
</dependency>

<dependency>
  <groupId>groupId</groupId>
  <artifactId>artifactId</artifactId>
  <version>version2</version>
  <scope>compile</scope>
</dependency>

The sequence matters here. need to have test first and then compile.

zheng
  • 41
  • 2
0
<dependency>
  <groupId>groupId.</groupId>
  <artifactId>artifactId</artifactId>
  <version>version1</version>
  <scope>test</scope>
</dependency>

<dependency>
  <groupId>groupId</groupId>
  <artifactId>artifactId</artifactId>
  <version>version2</version>
  <scope>compile</scope>
</dependency>

Adding a dot doesnt work in pom.xml as . is converted to slash which in return generated incorrect URL. Is thr any other way to do this

techAdi
  • 11
  • 1
  • This does not really answer the question. If you have a different question, you can ask it by clicking [Ask Question](https://stackoverflow.com/questions/ask). To get notified when this question gets new answers, you can [follow this question](https://meta.stackexchange.com/q/345661). Once you have enough [reputation](https://stackoverflow.com/help/whats-reputation), you can also [add a bounty](https://stackoverflow.com/help/privileges/set-bounties) to draw more attention to this question. - [From Review](/review/late-answers/31409358) – MrBrushy Mar 31 '22 at 16:18
-5

It's a really bad idea to have two different versions for compile and test dependency:

Your non-test code might rely on behavior of the newer JAR and fail when using classes of the older JAR. When you use the older JAR in your tests, the non-test code would fail with the old JAR.

Otherwise you could have used the older JAR anywhere, with the same version... If you get both JAR versions into your classpath, you cannot know which one gets picked up when running your tests. That's also a bad idea.

Hence you should get non-test and test to the same JAR version dependency.

  • 11
    The question is not whether someone should or should not have two versions of the same jar for main & test. The question is how can it be done. – Taylor Oct 10 '18 at 18:34
  • I would understand argument with keeping test and runtime with the same version but for compile it is different story. Example use case: I have library with guava and I am deploying it in two apps - first is using older guava and other is using newer guava. Obviously that works only if guava is backward compatible and if is then I want to compile library against older guava to ensure that it is using only guava API from older version. In C++ it would mean older header files and newer implementation. I like Go approach for backward compatibility and it's shame Java doesn't practice similar. – kodstark Aug 31 '23 at 11:32