简体   繁体   中英

Multiple maven modules to separate tests, api and implementation

I want to create a maven project with several implementations in separate modules of several interfaces declared in one api module (for the context, I'm writing a java persistence labs where students has to implement several time the services and repositories starting from simple JDBC to JPA then spring-data-jpa).

There is several maven modules in the project:

  • the root maven multiple-modules module, including the three submodules
  • the api module, containing the API interfaces
  • the api-tests module, containing the tests related to the API interfaces
  • the main module, containing one of the implementation of API

Root project module

The main maven project declares three submodules:

<?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">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.kartoch.stack</groupId>
    <artifactId>multiple-modules</artifactId>
    <packaging>pom</packaging>
    <version>1.0-SNAPSHOT</version>
    <modules>
        <module>api</module>
        <module>main</module>
        <module>tests</module>
    </modules>

</project>

API module

The API declares the interface:

public interface MustReturnTrue {

    boolean askMeTrue();
}

The related pom.xml of the api submodule:

<?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>multiple-modules</artifactId>
        <groupId>org.kartoch.stack</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <packaging>jar</packaging>
    <artifactId>api</artifactId>


</project>

Tests module

In this module, tests are wrote against the API interface:

import org.junit.Test;

import static org.junit.Assert.assertTrue;

public class MustReturnTrueTest extends Template {


    @Test
    public void testAskMeTrue() {
        assertTrue(mustReturnTrue.askMeTrue());
    }
}

Because the implementation of the API interface is submodule-dependant, an abstract class is available in the test package, and need to be implemented in each implementation module:

public abstract class Template {

    public MustReturnTrue mustReturnTrue;
}

For both classes, the code is in src/main/java directory and not src/test/java directory as I use the preferred way to create a jar containing test classes :

The related pom.xml of the tests submodule.

<?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>multiple-modules</artifactId>
        <groupId>org.kartoch.stack</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <packaging>jar</packaging>
    <artifactId>api-tests</artifactId>


    <dependencies>
        <dependency>
            <groupId>org.kartoch.stack</groupId>
            <artifactId>api</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
    </dependencies>

</project>

Main module

Finally, the main module contains one implementation of the API interfaces (in src/main/java ):

public class MustReturnTrueImpl implements MustReturnTrue { public boolean askMeTrue() { return true; } }

And the template implementation for test (in src/test/java ):

import org.junit.Before;

public class TemplateInitialization extends Template {

    @Before
    public void before() {
        mustReturnTrue = new MustReturnTrueImpl();
    }
}

The related pom.xml of the main submodule:

<?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>multiple-modules</artifactId>
        <groupId>org.kartoch.stack</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <packaging>jar</packaging>

    <artifactId>main</artifactId>

    <dependencies>
        <dependency>
            <groupId>org.kartoch.stack</groupId>
            <artifactId>api</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>org.kartoch.stack</groupId>
            <artifactId>api-tests</artifactId>
            <version>1.0-SNAPSHOT</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

</project>

The problem

What I expect during tests is that the tests in the tests module are executed against the implementation after initialization of the implementation by the class implementing Template .

But for unknown reason the tests are not executed during main test lifecycle:

-------------------------------------------------------
 T E S T S
-------------------------------------------------------

Results :

Tests run: 0, Failures: 0, Errors: 0, Skipped: 0

Any idea ?

Edit 1

I've the impression that the problem is the heriting is not working as expected. As TemplateInitialization is heriting Template which contains no tests, there is no tests executed: tests in MustReturnTrueTest are not "magically" imported. I need a way to load the TemplateInitialization at runtime before the tests.

Your template initialization should be done directly in the test class:

import org.junit.Test;

import static org.junit.Assert.assertTrue;

public class MustReturnTrueTest extends Template {

    @Before
    public void before() {
        mustReturnTrue = new MustReturnTrueImpl();
    }

    @Test
    public void testAskMeTrue() {
        assertTrue(mustReturnTrue.askMeTrue());
    }
}

If you need an instanciation before each test, use the JUnit @Before annotation.

If you need the instanciation to happen once, before all the tests in the test class, use @BeforeClass .


Edit:

And I would advise you to put the tests along the implementation code (in the main project), as per Maven standards.

In maven standard tests are written in the tested project, end respect some notation : http://maven.apache.org/guides/introduction/introduction-to-the-pom.html

 <build>
    <directory>target</directory>
    <outputDirectory>target/classes</outputDirectory>
    <finalName>${artifactId}-${version}</finalName>
    <testOutputDirectory>target/test-classes</testOutputDirectory>
    <sourceDirectory>src/main/java</sourceDirectory>
    <scriptSourceDirectory>src/main/scripts</scriptSourceDirectory>
    <testSourceDirectory>src/test/java</testSourceDirectory>
    <resources>
      <resource>
        <directory>src/main/resources</directory>
      </resource>
    </resources>
    <testResources>
      <testResource>
        <directory>src/test/resources</directory>
      </testResource>
    </testResources>
  </build>

So if you do not want override default pom configuration you have to implement test in src/test/java in your tests module

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM