skip to content

Surefire (Unit Tests)

Running unit tests in the test phase: include and exclude patterns, forking and parallelism, -Dtest filtering, and the two different ways to skip. The skipTests versus maven.test.skip distinction is a common trick question.

on this pageshow

questions

6

What is the Maven Surefire plugin and at which point in the build lifecycle does it run unit tests?

level: juniorimportance: must knowfreq 78%

answer

  1. test phase
  2. default include patterns *Test
  3. target/surefire-reports
  4. Surefire=unit, Failsafe=IT
  5. forked JVM by default

basics

~10 s

Surefire is the Maven plugin that runs your unit tests. It binds to the test phase of the default lifecycle, so tests run automatically during mvn test, package, install, and verify.

solid answer

~40 s

maven-surefire-plugin executes unit tests during the test phase of Maven's default lifecycle. Because compile and test-compile run before it, running mvn test (or any later phase like package/install/verify) compiles main and test sources and then runs the tests. By default it scans the test-classes output for classes matching **/Test*.java, **/*Test.java, **/*Tests.java, and **/*TestCase.java, runs them via a test provider (JUnit 4, JUnit Platform/Jupiter, or TestNG depending on what's on the classpath), and writes reports to target/surefire-reports. A failing test fails the build. Surefire is for unit tests; its sibling, the Failsafe plugin, handles integration tests in the integration-test/verify phases so a failed IT doesn't skip post-integration cleanup.

code

bash · 5 lines
bash
# Runs validate->compile->test-compile->test (Surefire)
mvn test

# Reports land here:
# target/surefire-reports/*.txt and *.xml

go deeper

for a junior

Know Surefire runs unit tests in the test phase and a failing test fails the build.

for a middle

Know the default include patterns and that compile/test-compile run first; reports go to target/surefire-reports.

for a senior

Explain the Surefire/Failsafe split and why deferring IT failure to verify matters for cleanup.

for a principal

Define the team convention for unit vs integration naming and ensure CI consumes the surefire/failsafe XML uniformly.

## What Surefire is Maven builds run through a fixed sequence of **phases** called the *default lifecycle*: `validate` -> `compile` -> `test-compile` -> `test` -> `package` -> `verify` -> `install` -> `deploy`. Each phase has **plugins** bound to it that do the actual work. The `maven-surefire-plugin` is bound to the **`test`** phase, so it is the component that actually runs your unit tests. Because phases run in order, invoking a phase runs every phase before it. So `mvn test` first runs `compile` (build `src/main/java`) and `test-compile` (build `src/test/java`), then Surefire executes the compiled tests. Running `mvn package`, `install`, or `verify` therefore also runs the unit tests unless you skip them. ## What it does - Scans `target/test-classes` for test classes matching the default include patterns: `**/Test*.java`, `**/*Test.java`, `**/*Tests.java`, `**/*TestCase.java`. - Picks a **provider** based on the classpath: JUnit 4, the JUnit Platform (for JUnit 5 / Jupiter), or TestNG. - Runs the tests, by default in a **separate (forked) JVM**. - Writes XML + plain-text reports to `target/surefire-reports`. - **Fails the build** if any test fails or errors (configurable via `testFailureIgnore`). ## Surefire vs Failsafe Surefire is for fast **unit tests**. Long-running **integration tests** use the `maven-failsafe-plugin`, which binds to `integration-test` and `verify`. Failsafe deliberately does not fail the build immediately on a failed test; it records the result and fails in `verify`, so the `post-integration-test` phase (e.g. shutting down a server/container) still runs. ```bash mvn test # compile + test-compile + run unit tests via Surefire mvn package # all of the above, then build the jar/war ```

  • Where does Surefire write its reports?
    To target/surefire-reports, as both plain-text (.txt) and JUnit-style XML (.xml) files; CI tools parse the XML.
  • Why is there a separate Failsafe plugin?
    So integration tests run in integration-test/verify and a failure is deferred to verify, letting post-integration-test cleanup (stopping servers/containers) still execute.

Surefire is the quality-control station on the assembly line: every unit passes through it during the test phase before the product (jar) gets packaged.

saying these in an interview costs you the question

  • Saying Surefire runs in the package phase (it runs in test).
  • Claiming Surefire runs integration tests (that's Failsafe).
  • Thinking mvn install skips tests by default.

context

open as a page

How do you control which tests Surefire runs using includes/excludes patterns and the -Dtest command-line filter?

level: middleimportance: must knowfreq 70%

basics

~10 s

Configure <includes>/<excludes> patterns in the plugin to match test class names. From the command line, run a subset with -Dtest=ClassName, -Dtest=ClassName#method, or wildcards like -Dtest='*IT' to override the defaults for that run.

open as a page

What is the difference between -DskipTests and -Dmaven.test.skip, and when would you use each?

level: middleimportance: must knowfreq 72%

basics

~20 s

-DskipTests compiles test classes but does not run them. -Dmaven.test.skip=true skips both compiling and running tests. Use skipTests to build a jar fast while keeping tests compilable; use maven.test.skip only when you also want to skip test compilation.

open as a page

How does Surefire use forkCount, reuseForks, and parallel to run tests, and how do these interact?

level: seniorimportance: should knowfreq 52%

basics

~20 s

forkCount sets how many separate JVMs run tests at once (e.g. 1C = one per CPU core); reuseForks decides whether a JVM is reused across test classes or recycled. parallel controls threads WITHIN a JVM (methods/classes) via the provider. Forking = process-level, parallel = thread-level.

open as a page

How does Surefire choose between JUnit 4, JUnit 5 (Jupiter), and TestNG providers, and how do you wire JUnit 5 correctly?

level: seniorimportance: should knowfreq 48%

basics

~20 s

Surefire auto-detects the test framework from your test-scoped dependencies and selects a matching provider. For JUnit 5 you add junit-jupiter (API + engine); modern Surefire (2.22+/3.x) discovers the JUnit Platform automatically, so you usually need no extra provider dependency.

open as a page

As a tech lead, how would you design a fast, reliable Surefire test-execution strategy across a large multi-module build?

level: principalimportance: nice to knowfreq 28%

basics

~20 s

Split fast unit tests (Surefire) from slow integration tests (Failsafe), parallelize units with forkCount per core while keeping per-fork resource isolation, pin one Surefire and test-framework version via parent POM, and enforce deterministic, thread-safe tests so the suite stays both fast and reliable.

open as a page