Maven Surefire

Classloader getResource() returns resource from wrong directory

Details

  • Type: Bug Bug
  • Status: Closed Closed
  • Priority: Major Major
  • Resolution: Cannot Reproduce
  • Affects Version/s: 2.4.2
  • Fix Version/s: None
  • Component/s: classloading
  • Labels:
    None
  • Complexity:
    Intermediate
  • Number of attachments :
    0

Description

In upgrading from version 2.3 to 2.4.2, we encountered a different behaviour in classloading. We have a classes/ and a test-classes/ folder under target, and both contain the same package, "foo":

|-- target/test-classes
|   `-- foo
        `-- some file
|-- target/classes
    `-- foo

In 2.3, a Classloader.getResource() call in our app returns the target/test-classes/foo folder, in which we find some file.

In 2.4.2, the same code returns the target/classes/foo folder, and so some file cannot be found. Note that there are two actual directories that resolve to from same classpath location.

To get the classes folder in the classpath when running tests, we are using this testResources in the pom:
<noformat>
<testResources>
<!-- include the standard resource directory... -->
<testResource>
<directory>src/test/resources</directory>
</testResource>
<!--
... and include the resources from the real build, but give
precedence to any test resources with the same name (this is
accomplished by defining this testResource after the previous one.
-->
<testResource>
<directory>src/main/resources</directory>
</testResource>
</testResources>
</noformat>

Perhaps SUREFIRE-443 can provide a way to correctly copy resources between the classes and test-classes folders, so that there is only one location on the disk for each classpath URI.

Activity

Hide
Dan Fabulich added a comment -

I had a long thread about this issue on the Maven users list.

http://www.nabble.com/Surefire-2.4.1-classpath-order-tt15498825s177.html

Here's a summary:

The resource retrieved is the one that appears first in the test classpath; if you're getting the "wrong" resource, it's because your classpath is in the wrong order, which is often due to a Maven bug, but it's often very non-obvious why that would be.

Take a look at http://jira.codehaus.org/browse/MNG-3118. That bug was fixed in Maven 2.0.8 and called out in the release announcement as a backwards compatibility risk:

http://www.mail-archive.com/announce@apache.org/msg00432.html

As noted in MNG-3118, Surefire 2.3 had a bizarre classpath ordering bug that made the test classpath appear to be correct (test-classes first) under Maven 2.0.7 for some users with large classpaths:

http://jira.codehaus.org/browse/SUREFIRE-61

SUREFIRE-61 was fixed in Surefire 2.3.1. Notably, it would make the "Test Classpath" output in -X look correct, while secretly under the hood it would munge the classpath incorrectly!

As a result, for at least one project here at my work, we've seen:

Maven 2.0.7 + Surefire 2.3: test-classes before classes
Maven 2.0.8 + Surefire 2.3: classes before test-classes
Maven 2.0.7 + Surefire 2.3.1 or higher: classes before test-classes
Maven 2.0.8 + Surefire 2.3.1 or higher: test-classes before classes

Benjamin checked in a classpath ordering test in the Surefire trunk that we now run with every release. It's currently passing for me with Surefire 2.4.1 (and 2.4.2-SNAPSHOT) and Maven 2.0.8, and failing with Maven 2.0.7.

Finally, note that your "real" classpath is being output in your target/surefire-reports/*.xml files as the "surefire.test.classpath" property; that may be useful for debugging purposes.

Show
Dan Fabulich added a comment - I had a long thread about this issue on the Maven users list. http://www.nabble.com/Surefire-2.4.1-classpath-order-tt15498825s177.html Here's a summary: The resource retrieved is the one that appears first in the test classpath; if you're getting the "wrong" resource, it's because your classpath is in the wrong order, which is often due to a Maven bug, but it's often very non-obvious why that would be. Take a look at http://jira.codehaus.org/browse/MNG-3118. That bug was fixed in Maven 2.0.8 and called out in the release announcement as a backwards compatibility risk: http://www.mail-archive.com/announce@apache.org/msg00432.html As noted in MNG-3118, Surefire 2.3 had a bizarre classpath ordering bug that made the test classpath appear to be correct (test-classes first) under Maven 2.0.7 for some users with large classpaths: http://jira.codehaus.org/browse/SUREFIRE-61 SUREFIRE-61 was fixed in Surefire 2.3.1. Notably, it would make the "Test Classpath" output in -X look correct, while secretly under the hood it would munge the classpath incorrectly! As a result, for at least one project here at my work, we've seen: Maven 2.0.7 + Surefire 2.3: test-classes before classes Maven 2.0.8 + Surefire 2.3: classes before test-classes Maven 2.0.7 + Surefire 2.3.1 or higher: classes before test-classes Maven 2.0.8 + Surefire 2.3.1 or higher: test-classes before classes Benjamin checked in a classpath ordering test in the Surefire trunk that we now run with every release. It's currently passing for me with Surefire 2.4.1 (and 2.4.2-SNAPSHOT) and Maven 2.0.8, and failing with Maven 2.0.7. Finally, note that your "real" classpath is being output in your target/surefire-reports/*.xml files as the "surefire.test.classpath" property; that may be useful for debugging purposes.
Hide
Dan Fabulich added a comment -

As mentioned, we've got an integration test checked in that verifies this behavior explicitly. If it's not working for you, then please reopen this bug and provide a reduced test case demonstrating the problem, ideally in the form of a minimal Maven project that has the bug.

Show
Dan Fabulich added a comment - As mentioned, we've got an integration test checked in that verifies this behavior explicitly. If it's not working for you, then please reopen this bug and provide a reduced test case demonstrating the problem, ideally in the form of a minimal Maven project that has the bug.
Hide
Alex Eagle added a comment -

Thanks for the detailed reply, Dan. The issue with incorrectly reporting the classpath may have been part of our problem. Your listing of Maven vs. Surefire versions is correct, with Maven 2.0.8 and Surefire 2.4.2, we get the correct classpath ordering and our test runs successfully.

It may be that in our earlier testing, we thought we were running 2.0.8 but were actually running 2.0.6. Cannot reproduce is the right resolution

Show
Alex Eagle added a comment - Thanks for the detailed reply, Dan. The issue with incorrectly reporting the classpath may have been part of our problem. Your listing of Maven vs. Surefire versions is correct, with Maven 2.0.8 and Surefire 2.4.2, we get the correct classpath ordering and our test runs successfully. It may be that in our earlier testing, we thought we were running 2.0.8 but were actually running 2.0.6. Cannot reproduce is the right resolution

People

Vote (0)
Watch (0)

Dates

  • Created:
    Updated:
    Resolved: