views:

43

answers:

2

I have a multi module Spring project that I set up using Maven:

my-root (pom)
    - my-logic
    - my-webapp (depending on my-logic)
    - my-consoleapp (depending on my-logic)

My Test classes inherit from AbstractTransactionalJUnit4SpringContextTests and use @ContextCofiguration for setting up the ApplicationContext.

E.g. the test class for a Spring Controller:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { 
  "classpath:applicationContext-logic-test.xml",
  "classpath:applicationContext-web-test.xml"})
public class ControllerTest extends AbstractTransactionalJUnit4SpringContextTests {

  @Autowired
    private ApplicationContext applicationContext;
    ...
}

As you can see there is a config XML per module. I have seperate configs for tesing, residing in test/resources of each module (and additionaly having the suffix "-test"). This all works (the class compiles, runs and the JUnit tests are successful) if I run the JUnit test in Eclipse.

Now to my problem: Running the test using Maven will NOT work! (e.g. with "Run As">"Maven install" on my-root (I use m2eclipse)). Specifically, it will throw the following exception:

java.io.FileNotFoundException: class path resource [applicationContext-logic-test.xml] cannot be opened because it does not exist`

It seems that Maven does not add the files from my-logic/src/test/resources to the classpath that is set up when running the unit tests of my-webapp.

How can I fix that?

+1  A: 

That's by design. Test resources are not placed into the output artifact, so any test dependencies of something you depend on would not be accessible, even in your unit test classpath.

If you want to accomplish what you're trying to do you should create a project which contains the resources you need for testing and make it a test scoped dependency of both my-logic and my-webapp

Jherico
+3  A: 

It seems that Maven does not add the files from my-logic/src/test/resources to the classpath that is set up when running the unit tests of my-webapp.

No, indeed, it doesn't. First, Maven uses binary dependencies that are always resolved through the local repository. And second, binary dependencies don't include test stuff.

But what you could do is:

  1. configure the my-logic module to create a test JAR using jar:test-jar
  2. configure the my-webapp module to depend on this test JAR (using a test scope).

For #1, you'll have to configure the Maven Jar Plugin in the pom.xml of my-logic:

<project>
  <build>
    <plugins>
     <plugin>
       <groupId>org.apache.maven.plugins</groupId>
       <artifactId>maven-jar-plugin</artifactId>
       <version>2.2</version>
       <executions>
         <execution>
           <goals>
             <goal>test-jar</goal>
           </goals>
         </execution>
       </executions>
     </plugin>
    </plugins>
  </build>
</project>

And Maven will create a JAR with the content of target/test-classes during package and install / deploy it.

For #2, declare a dependency on the test JAR in the pom.xml of my-webapp:

<project>
  ...
  <dependencies>
    <dependency>
      <groupId>com.myco.app</groupId>
      <artifactId>foo</artifactId>
      <version>1.0-SNAPSHOT</version>
      <type>test-jar</type>
      <scope>test</scope>
    </dependency>
  </dependencies>
  ...
</project>

That should do it.

Pascal Thivent
Thanks a lot for this excellent answer! I used this solution and it works. Now that you explained this it's obvious to me as well that test resources of all (external) dependencies are not included in the classpath. How should they? But somehow it would be nice if resources from my own modules would be included. Even though I don't know how exactly this would work, now that I think about it ;)
apropoz
@apropoz You're welcome. The idea with Maven is that modules are self contained: you can checkout a single module without its brothers and build it. Anything that would involve relative paths would break this, which is not desirable.
Pascal Thivent