Aleksandr Zorin
Aleksandr Zorin

Reputation: 47

Test resources not added to classpath

The test resources aren't been added to classpath when building the project with Maven

The structure of project:

project/pom.xml
   /dist/pom.xml
        /src/main/resources/db/test.sql
   
   /test/pom.xml
        /src/test/com/loader/TestLoader.java

Here is pom.xml of dist module:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>test1</artifactId>
        <groupId>org.example</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>dist</artifactId>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-jar-plugin</artifactId>
                <version>3.2.0</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>test-jar</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>build-helper-maven-plugin</artifactId>
                <version>1.12</version>
                <executions>
                    <execution>
                        <id>add-test-resource</id>
                        <phase>generate-test-sources</phase>
                        <goals>
                            <goal>add-test-resource</goal>
                        </goals>
                        <configuration>
                            <resources>
                                <resource>
                                    <directory>src/main/resources</directory>
                                </resource>
                            </resources>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

Here is pom.xml of test module:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>test1</artifactId>
        <groupId>org.example</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>test</artifactId>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>11</source>
                    <target>11</target>
                </configuration>
            </plugin>
        </plugins>
    </build>

    <dependencies>
        <!-- https://mvnrepository.com/artifact/junit/junit -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13.2</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <artifactId>dist</artifactId>
            <groupId>org.example</groupId>
            <version>1.0-SNAPSHOT</version>
            <type>test-jar</type>
            <scope>test</scope>
        </dependency>
    </dependencies>
</project>

And the JUnit test which tries to read test.sql from dist's module

@RunWith(JUnit4.class)
public class TestLoader {

    @Test
    public void test() throws Exception {
        Path path = Paths.get(ClassLoader.getSystemResource("db/test.sql").toURI());

        System.out.println(path.toFile().exists());
    }

When I run this test from IDEA, everything is OK, but when I try with command mvn clean install, I get error that resources are not found.

What could be the error?

Upvotes: 0

Views: 1867

Answers (1)

Tigger
Tigger

Reputation: 439

File detection

ClassLoader.getSystemResource() will return a different kind of URL depending on how the test class is executed:

  • from an IDE, it's a file ("file:/path/to/db/test.sql"), so Path.get(uri) is OK
  • from Maven, it's a JAR (ZIP) entry ("jar:file:/path/to/dist-1.0-SNAPSHOT.jar!/db/test.sql"), so Path.get(uri) throws a FileSystemNotFoundException

The URL is enough to know if the entry exists.
If so, its content can be read using url.openStream().

URL url = ClassLoader.getSystemResource("db/test.sql");
if (url == null) {
    // File not found
} else {
    try (InputStream is = url.openStream()) {
        (...)
    }
}

Maven configuration

Depending on the dist module's goal, 2 configurations are possible.

1- dist is part of an API that will be tested in test

Then no need to use the test-jar execution goal at all.

  • dist/pom.xml : the entire build section can be removed
  • test/pom.xml : fine as it is
2- dist is dedicated to tests only (in test module and maybe others)

Then, it's more consistent to put the dist resources in the test directory.

  • db/test.sql should be moved to dist/src/test/resources
  • dist/pom.xml : the test-jar part remains, but the build-helper-maven-plugin becomes useless and can be removed
  • test/pom.xml : to make it work, a dependency classifier is mandatory
<dependency>
    <groupId>${project.groupId}</groupId>
    <artifactId>dist</artifactId>
    <version>${project.version}</version>
    <scope>test</scope>
    <classifier>tests</classifier>
</dependency>

Upvotes: 1

Related Questions