Using JUnit

Configuring JUnit

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

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

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

Different Generations of JUnit support

Surefire supports three different generations of JUnit: JUnit 3.8.x, JUnit 4.x (serial provider) and JUnit 4.7 (junit-core provider with parallel support). The provider is selected based on the JUnit version in your project and the configuration parameters (for parallel).

Upgrade check for JUnit 4.x

As of Surefire version 2.7, the algorithm for choosing which tests to run has changed. From 2.7 and on, only valid JUnit tests are run for all versions of JUnit, where older versions of the plugin would also run invalid tests that satisfied the naming convention.

When upgrading from a Surefire version prior to 2.7, the build can be run with the flag -Dsurefire.junit4.upgradecheck. This will perform a check and notify you of any invalid tests that will not be run with this version of Surefire (and the build fails). This is only meant to be used as a tool when upgrading to check that all expected tests will be run. It is a transitional feature that will be removed in a future version of surefire.

How is the provider chosen ?

If nothing is configured, surefire detects which junit version to use by the following algorithm:

if the JUnit version in the project >= 4.7 and the parallel attribute has ANY value
    use junit47 provider
if JUnit >= 4.0 is present
    use junit4 provider
else
    use junit3.8.1

Please note that the "else" part of this algorithm is also a FAQ response:

You depend on the appropriate version of JUnit being present in the project dependencies, or surefire may choose the wrong provider. If, for instance, one of your dependencies pulls in JUnit 3.8.1 you risk that surefire chooses the 3.8.1 provider, which will not support annotations or any of the 4.x features.

Use mvn dependency:tree, pom dependency ordering and/or and exclusion of transitive dependencies to fix this problem.

Manually specifying a provider

You can also manually force a specific provider by adding it as a dependency to surefire itself:

[...]
  <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-surefire-plugin</artifactId>
    <version>2.9</version>
    <dependencies>
      <dependency>
        <groupId>org.apache.maven.surefire</groupId>
        <artifactId>surefire-junit47</artifactId>
        <version>2.9</version>
      </dependency>
    </dependencies>
[...]

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

From JUnit 4.7 and onwards you can run your tests in parallel. To do this, you must set the parallel parameter, and may change the threadCount or useUnlimitedThreads attribute. For example:

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

If your tests specify any value for the "parallel" attribute and your project uses JUnit 4.7+, your request will be routed to the concurrent JUnit provider, which uses the JUnit JUnitCore testrunner.

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

As of surefire 2.7, no additional dependencies are needed to use the full set of options with parallel.

Using custom listeners and reporters

JUnit4/4.7 provider provides support for attaching custom RunListeners to uour tests.

You can configure multiple custom listeners like this:

[...]
  <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-surefire-plugin</artifactId>
    <version>2.9</version>
    <configuration>
      <properties>
        <property>
          <name>listener</name>
          <value>com.mycompany.MyResultListener,com.mycompany.MyResultListener2</value>
        </property>
    </configuration>
  </plugin>
[...]

Using a security manager (JUnit3 only)

As long as forkMode!=never and you use JUnit3, you can run your tests with a java security manager active. The classname of the security manager must be sent as a system property variable to the JUnit3 provider.

JUnit4 uses mechanisms internally that are not compatible with the tested security managers and is not supported by surefire.

[...]
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-surefire-plugin</artifactId>
        <version>2.9</version>
        <configuration>
          <systemPropertyVariables>
            <surefire.security.manager>java.lang.SecurityManager</surefire.security.manager>
          </systemPropertyVariables>
        </configuration>
      </plugin>
[...]

Using a security manager (All providers)

Alternatively you can define a policy file that allows all providers to run with surefire and send them using the argLine parameter and two system properties;

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

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

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