Testing with Surefire and Failsafe

Maven · Essentials · 8 min

Test execution is where most day-to-day Maven interaction happens.

The Surefire plugin runs unit tests in the test phase. It picks up classes named *Test, Test*, *Tests or *TestCase from src/test/java. For JUnit 5, add org.junit.jupiter:junit-jupiter with test scope; Surefire 3.x detects the JUnit Platform automatically. Pin the Surefire version in <build><plugins> (or a parent) because the default bound version may be old.

Filtering and options:

  • mvn test -Dtest=UserServiceTest or -Dtest='User*Test#create*' for a class or methods.
  • -Dsurefire.failIfNoSpecifiedTests=false when a filter matches nothing in some modules.
  • -DskipTests to skip; -Dmaven.test.failure.ignore=true to continue despite failures.
  • Configure JVM args, system properties, parallelism (<forkCount>, <parallel>) and includes/excludes in the plugin's <configuration>.

Reports go to target/surefire-reports/ (text and JUnit XML for CI).

Failsafe is Surefire's sibling for integration tests. It runs *IT classes in the integration-test phase and only fails the build in verify, so a post-integration-test phase can still tear down containers or servers. You must add it explicitly with executions for integration-test and verify. Run mvn verify to include it.

Test output is captured by default; set <redirectTestOutputToFile> or use -Dsurefire.printSummary and look in the reports when debugging.

Example

<build>
  <plugins>
    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-surefire-plugin</artifactId>
      <version>3.5.2</version>
      <configuration>
        <excludedGroups>slow</excludedGroups>         <!-- JUnit 5 @Tag("slow") -->
        <systemPropertyVariables>
          <app.env>test</app.env>
        </systemPropertyVariables>
      </configuration>
    </plugin>
    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-failsafe-plugin</artifactId>
      <version>3.5.2</version>
      <executions>
        <execution>
          <goals><goal>integration-test</goal><goal>verify</goal></goals>
        </execution>
      </executions>
    </plugin>
  </plugins>
</build>
<!-- mvn test -Dtest=UserServiceTest        -> unit tests only
     mvn verify                             -> unit tests + *IT integration tests
     reports: target/surefire-reports, target/failsafe-reports -->

Remember

  • Surefire runs *Test classes in the test phase
  • Failsafe runs *IT classes in integration-test and fails in verify
  • -Dtest=Class#method filters; -DskipTests skips
  • Reports land in target/surefire-reports

Watch out for

  • Naming an integration test *Test, so it runs with the fast unit tests on every mvn test.

Check yourself

  1. Why does Failsafe fail the build in verify rather than in integration-test?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: maven.apache.org/surefire/maven-surefire-plugin/

Builds on

Unlocks

Nothing builds on this yet.