Sri Sankaran
Sri Sankaran

Reputation: 8320

Unable to get Maven (and Eclipse) to use test resources while testing

I am having trouble getting unit tests to use resources provided under src\test\resources instead of those in src\main\resources. Yes, the resource in question is named identically in both places.

I have done a fair amount of research, looked at StackOverflow posts such as:

However this basic issue has me stumped.

I have a very standard Maven Java project set up:

Eclipse (thanks to M2Eclipse plugin) has src\main\java, src\main\resources, src\test\java and src\test\resources all in its build path.

With this setup, when I run my unit test from within Eclipse resource files in src\main\resources are being referenced. I can see why (because they are in the build path) but I don't know how to prevent it. The unit test configuration panel does not allow me to tweak the order of (default) classpath components.

Even if I were to gloss over my inability to run my tests from Eclipse, Maven doesn't play nice either. I can see that the processResources step is copying all the test resources to under the target\test-classes tree. However when the unit test is executed the copy of the resource file under target\classes is being consulted.

Surely I am overlooking something obvious. I appreciate any help you can provide.

[EDIT] Adding more (possibly relevant information):

The resource file in question is a file named persistence.xml. It is used by Eclipselink to connect to relational data sources. The version of the file used by the application is placed in src\main\resources\META-INF. A Maven build (of a WAR, say) places the META-INF directory under the classes directory. Therefore EclipseLink tooling finds this file.

src/main
  |
  + -- java/com/company/ProductDao.java
  | 
  + -- resources/META-INF/persistence.xml  (Requires application container)
  |
src/test
  |
  + -- java/com/company/ProductDaoTest.java
  | 
  + -- resources/META-INF/persistence.xml  (out of container for unit tests)
  |

The takeaway here is: EclipseLink requires a file called persistence.xml in a META-INF directory on the classpath (yes, defaults can be overridden but let's not go there).

Therefore when the unit test runs the same application logic is invoked. However the version of the file in src\main\resources cannot be used. A different version is made available in the src\test\resources directory.

Since the version in src\main\resources is being used it appears that my only recourse is to instruct Eclipselink during unit testing to look for a different filename.

Upvotes: 1

Views: 4288

Answers (2)

user3756435
user3756435

Reputation: 1

I answered and then had to spent few moments trying to figure it out again. In the surefire documentation it says that test-classes should be first in classpath : http://maven.apache.org/surefire/maven-surefire-plugin/examples/configuring-classpath.html

And surefire shows (with mvn --debug option): [DEBUG] test classpath:
...\target\test-classes
...\target\classes ....m2\repository\javax\enterprise\cdi-api\1.2\cdi-api-1.2.jar
....m2\repository\javax\el\javax.el-api\3.0.0\javax.el-api-3.0.0.jar ... but stil it uses target\classes first. Strange this bug was reported some time ago. Then whatever I do the persistence.xml from classes folder is taken first.

So I had to use two persistence units in one persistence.xml file what might be not the best but works fine also.

Upvotes: 0

Andrew T Finnell
Andrew T Finnell

Reputation: 13638

This isn't a Maven issue at the root of it. You'd have the exact same problem if you had everything collapsed into a single source folder. Think about what you are really doing. Your unit tests require the code from src/main or else it wouldn't be a unit test of that code. src/main/java and src/main/resources make up the artifact you are testing. You don't mix and match the directories for your unit test.

You are basically doing this:

/src/com/mycompany/myresource.txt        
/src/com/mycompany/MyAwesomeClass.java
/src/com/mycompany/myresource.txt
/src/com/mycompany/TestMyAwesomeClass.java

Don't do that. Configure your unit tests to load mock data / your resource file from another file.

I haven't had many, if any issues with Maven and Eclipse. Realize that Maven is not magic. And that if you are going to use Maven and Eclipse everything has to be driven by the POM file not the other way around. Then things work beautifully.

Just to reclarify, your issue has nothing to do with Maven. You are declaring a resource twice on the classpath. You need to rethink your unit tests. There are things you can do to get around this with Profiles but it's an abuse of the build system.

Upvotes: 1

Related Questions