Search code examples
mavenjunitmaven-3maven-jar-plugin

How to create Maven Jar file when tests contain JUnit @Test annotations and no main class


I have 3 tests stored under a package that all take advantage of the JUnit @Test annotation. I do not have a main class in the project. Naturally, I can go Run As > Maven Test and all 3 tests will get executed.

I created a Jar executable file using the the Install command, but when I try to run the Jar file I get the message - "No main manifest attribute" message.

What is the solution for dealing with this in Maven?

I know that in Gradle, you do not need a main class to run the Jar executable.

Alternatively, would I need to create a main class containing a main method like this:

public static void main(String[] args){
List tests = new ArrayList();
tests.add(TestOne.class);
tests.add(TestTwo.class);

for (Class test : tests){
    runTests(test);
}
}

private static void runTests(Class test){
Result result = JUnitCore.runClasses(test);
for (Failure failure : result.getFailures()){
    System.out.println(failure.toString());
}
}

That kind of feels counter-intuitive to me however.


Solution

  • Generate test-jar

    You could add this into your pom.xml to generate a jar with your all your tests:

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

    Execute test class

    Then, execute the tests this way:

    java -cp yourproject-1.0.0-tests.jar:junit-4.12.jar:otherdependencies.jar \ 
         junit.textui.TestRunner com.xyz.SomeTest
    

    You need to add all your required dependencies in the -cp arguments.

    Test Suite

    Each test must be executed one by one, but you could create a testSuite, so you can easily execute all tests with a single command:

    @RunWith(Suite.class)
    @Suite.SuiteClasses({
            SomeTest.class,
            SomeOtherTest.class
    })
    public class SuiteAbcTest {
        //normally, this is an empty class
    }
    

    and execute the Test Suite:

    java -cp yourproject-1.0.0-tests.jar:junit-4.12.jar:otherdependencies.jar \ 
         junit.textui.TestRunner com.xyz.SuiteAbcTest