Fork me on GitHub

Using JUnit

Configuring JUnit

To get started with JUnit, you need to add the required version of JUnit to your project:

<dependencies>
  [...]
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.13.2</version>
      <scope>test</scope>
    </dependency>
  [...]
</dependencies>

This is the only step that is required to get started - you can now create tests in your test source directory (e.g., src/test/java).

JUnit Support in Surefire 3.6.0+

Since version 3.6.0, Surefire runs all JUnit tests via the JUnit Platform:

  • JUnit 5 tests are executed via the Jupiter Engine
  • JUnit 4 tests (4.12 or later) are executed via the Vintage Engine

Important: JUnit 4.12 is the minimum supported version. Earlier versions of JUnit 4 and JUnit 3.x are no longer supported. If you have JUnit 3 tests, they must be migrated to JUnit 4.12+ to run.

Provider Selection

Since Surefire 3.6.0, all tests run via the JUnit Platform provider (surefire-junit-platform):

if JUnit 5 Platform artifacts are present
    use junit-platform with Jupiter engine
if JUnit 4.12+ is present
    use junit-platform with Vintage engine
if JUnit < 4.12 is present
    ERROR: JUnit 4.12 or later is required

Note: If you have JUnit 3 or JUnit 4 (before 4.12) tests, you must upgrade your JUnit dependency to at least 4.12. JUnit 4.12+ tests can run unchanged via the Vintage Engine.

Manual Engine Configuration

Since Surefire 3.6.0, explicit provider configuration is rarely needed. However, you can add specific JUnit Platform engines as plugin dependencies if needed:

<plugins>
[...]
  <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-failsafe-plugin</artifactId>
    <version>3.6.0-SNAPSHOT</version>
    <dependencies>
      <dependency>
        <groupId>org.junit.vintage</groupId>
        <artifactId>junit-vintage-engine</artifactId>
        <version>5.9.1</version>
      </dependency>
    </dependencies>
  </plugin>
[...]
</plugins>

When using this technique there is no check that the proper test-frameworks are present on your project's classpath. Failing to add the proper test-frameworks will result in a build failure.

Running Tests in Parallel

You can run your tests in parallel using the parallel parameter:

<plugins>
    [...]
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-failsafe-plugin</artifactId>
        <version>3.6.0-SNAPSHOT</version>
        <configuration>
          <parallel>methods</parallel>
          <threadCount>10</threadCount>
        </configuration>
      </plugin>
    [...]
</plugins>

This is particularly useful for slow tests that can have high concurrency.

Additional thread-count attributes are available: threadCountSuites, threadCountClasses and threadCountMethods. The attributes parallelTestsTimeoutInSeconds and parallelTestsTimeoutForcedInSeconds can be used to shut down the parallel execution after an elapsed timeout.

See also Fork Options and Parallel Test Execution.

Using Custom Listeners and Reporters

When running JUnit 4 tests via the Vintage Engine, you can attach custom JUnit 4 RunListeners to your tests.

You can configure multiple custom listeners like this:

<dependencies>
[...]
  <dependency>
    <groupId>your-junit-listener-artifact-groupid</groupId>
    <artifactId>your-junit-listener-artifact-artifactid</artifactId>
    <version>your-junit-listener-artifact-version</version>
    <scope>test</scope>
  </dependency>
[...]
</dependencies>
[...]
<plugins>
[...]
  <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-failsafe-plugin</artifactId>
    <version>3.6.0-SNAPSHOT</version>
    <configuration>
      <properties>
        <property>
          <name>listener</name>
          <value>com.mycompany.MyResultListener,com.mycompany.MyResultListener2</value>
        </property>
      </properties>
    </configuration>
  </plugin>
[...]
</plugins>

For more information on JUnit, see the JUnit web site.

You can implement JUnit listener interface org.junit.runner.notification.RunListener in a separate test artifact your-junit-listener-artifact with scope=test, or in project test source code src/test/java. You can filter test artifacts by the parameter dependenciesToScan to load its classes in current ClassLoader of surefire-junit* providers.

Since JUnit 4.12 thread safe listener class should be annotated by org.junit.runner.notification.RunListener.ThreadSafe which avoids unnecessary locks in JUnit.

Using a Security Manager (All providers)

Alternatively you can define a policy file that allows all providers to run with Surefire and configure it using the argLine parameter and two system properties:

<plugins>
[...]
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-failsafe-plugin</artifactId>
        <version>3.6.0-SNAPSHOT</version>
        <configuration>
          <argLine>-Djava.security.manager -Djava.security.policy=${basedir}/src/test/resources/java.policy</argLine>
        </configuration>
      </plugin>
[...]
</plugins>

The disadvantage of this solution is that the policy changes will affect the tests too, which make the security environment less realistic.

Using JUnit Categories

JUnit 4.8 introduced the notion of Categories. You can use JUnit categories by using the groups parameter. Since Surefire 3.6.0, JUnit 4 categories work via the Vintage Engine.

<plugins>
[...]
    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-failsafe-plugin</artifactId>
        <version>3.6.0-SNAPSHOT</version>
        <configuration>
            <groups>com.mycompany.SlowTests</groups>
        </configuration>
    </plugin>
[...]
</plugins>

This will execute only those tests annotated with the @Category(com.mycompany.SlowTests.class) annotation and those tests annotated with @Category(com.mycompany.SlowerTests.class) if class/interface SlowerTests is subclass of SlowTests:

    public interface SlowTests{}
    public interface SlowerTests extends SlowTests{}
    public class AppTest {
      @Test
      @Category(com.mycompany.SlowTests.class)
      public void testSlow() {
        System.out.println("slow");
      }

      @Test
      @Category(com.mycompany.SlowerTests.class)
      public void testSlower() {
        System.out.println("slower");
      }

      @Test
      @Category(com.mycompany.FastTests.class)
      public void testSlow() {
        System.out.println("fast");
      }
    }

The @Category annotation can also be applied at class-level.

Multiple categories can be specified by comma-delimiting them in the groups parameter in which case tests annotated with any of the categories will be executed.

For more information on JUnit, see the JUnit web site.

Since version 2.18.1 and JUnit 4.12, the @Category annotation type is automatically inherited from superclasses, see @java.lang.annotation.Inherited. Make sure that test class inheritance still makes sense together with @Category annotation of the JUnit 4.12 or higher appeared in superclass.