1 Maven Command (mvn)
The basic syntax for running Maven is:
mvn [options] [<plugin:goal>] [<phase>]
The execution order depends on how goals and build phases are specified on the command line.
2 Running Maven Phases
Example: Compile a project
mvn clean compile
This command removes the previous build output and compiles the project's
source code.
3 Running Unit Tests and Integration Tests
Unit tests usually test individual classes or components in isolation.
Integration tests verify that multiple components work together, for example
an application communicating with a database.
Maven itself does not inherently know whether a test is a
unit test or an integration test.
The distinction is usually created through plugin configuration and test
class naming conventions.
Different Maven plugins can recognize different test class naming patterns.
For example, the maven-surefire-plugin is normally used for
unit tests, while the maven-failsafe-plugin is normally used for
integration tests.
3.1 How Maven Test Plugins Recognize Test Classes
Each test plugin has its own default include patterns. These patterns
determine which Java classes are considered test classes and executed by
the plugin.
For example, the maven-surefire-plugin, which is normally used
for unit tests, recognizes common test class names such as:
Test*.java
*Test.java
*Tests.java
*TestCase.java
Therefore, classes such as the following can be recognized as unit tests:
UserTest.java
TestUser.java
UserTests.java
UserTestCase.java
The maven-failsafe-plugin uses different default patterns for
integration tests:
IT*.java
*IT.java
*ITCase.java
Therefore, classes such as the following can be recognized as integration
tests:
ITDatabase.java
DatabaseIT.java
DatabaseITCase.java
This naming convention makes it possible to separate unit tests from
integration tests while keeping both types of tests in the same Maven test
source directory.
Example: Run Unit Tests
mvn test
This command executes the Maven lifecycle up to the test phase.
It compiles the application, compiles the test code, and runs the unit tests.
The unit tests are normally executed by the
maven-surefire-plugin.
For example:
mvn clean test
This command first removes the previous build output and then compiles and
executes the unit tests.
Example: Run Unit Tests and Integration Tests
mvn verify
The verify phase occurs later in the Maven default lifecycle.
Therefore, Maven executes all the preceding phases before reaching
verify.
If the project is configured with the maven-failsafe-plugin,
the integration tests are executed during the
integration-test and verify phases.
A common command is:
mvn clean verify
This command performs a clean build, runs the unit tests, packages the
application, and executes the integration tests.
The simplified execution flow is:
clean
|
compile
|
test
|---- Unit Tests
|
package
|
integration-test
|---- Integration Tests
|
verify
3.2 Running Integration Tests with Surefire
Using the maven-failsafe-plugin is the standard approach when
you want to separate unit tests from integration tests. However, using two
test plugins is not mandatory.
If you prefer to use only the maven-surefire-plugin, you can
name your integration test classes using one of Surefire's default test
patterns.
For example, both of the following classes match Surefire's default naming
conventions:
UserServiceTest.java
DatabaseIntegrationTest.java
Although DatabaseIntegrationTest.java is logically an
integration test, its name matches the *Test.java pattern.
Therefore, Surefire recognizes it as a test class and executes it together
with the unit tests.
For example, consider the following test structure:
src
|
+-- test
|
+-- java
|
+-- UserServiceTest.java
+-- RepositoryTest.java
+-- DatabaseIntegrationTest.java
+-- JpaIntegrationTest.java
All these classes match the default patterns recognized by the
maven-surefire-plugin.
Therefore, the following command executes both the unit tests and the
integration tests:
mvn test
Or, for a clean build:
mvn clean test
In this configuration, Maven does not distinguish between unit tests and
integration tests. Both types of tests are executed during the
test phase by the Surefire plugin.
UserServiceTest.java
RepositoryTest.java
|
+----> maven-surefire-plugin
|
DatabaseIntegrationTest.java
JpaIntegrationTest.java
|
+----> maven-surefire-plugin
|
v
test phase
This approach can be useful for small projects where running all tests
together is sufficient and a separate integration test lifecycle is not
required.
However, if integration tests require additional setup or cleanup operations,
such as starting and stopping a database, a container, or an external
service, using the maven-failsafe-plugin is usually the better
approach.
3.3 integration-test vs verify
The integration-test and verify phases are both
part of the Maven default lifecycle, but they have different purposes.
The command:
mvn integration-test
runs the Maven lifecycle up to the integration-test phase.
Therefore, all preceding phases are executed first.
In a project using the maven-failsafe-plugin, the integration
tests are executed during this phase.
For example, the execution flow can be summarized as:
mvn test
↓
Unit tests
mvn package
↓
Unit tests
↓
Package
mvn integration-test
↓
Unit tests
↓
Package
↓
Integration tests
mvn verify
↓
Unit tests
↓
Package
↓
Integration tests
↓
Verification of integration-test results
mvn install
↓
Unit tests
↓
Package
↓
Integration tests
↓
Verification of integration-test results
↓
Install artifact into local repository
mvn deploy
↓
Unit tests
↓
Package
↓
Integration tests
↓
Verification of integration-test results
↓
Install artifact into local repository
↓
Deploy artifact to remote repository
The important difference is that integration-test is the phase
where the integration tests are executed, while verify is a
later phase where the results of the integration-test execution can be
checked.
This is why the Maven Failsafe Plugin is normally configured with both the
integration-test and verify goals:
<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>
For this reason, when you want to perform a complete build including
integration tests, mvn verify is generally preferred over
mvn integration-test.
The commonly used command is:
mvn clean verify
This performs a clean build, runs the unit tests, packages the application,
runs the integration tests, and verifies their results.
In other words, integration-test is mainly the phase where
integration testing takes place, while verify is the phase
normally used to confirm that the complete build has successfully passed
all required checks.
4 Configuring Unit and Integration Tests
Maven uses plugins to execute tests. Each plugin can have its own rules for
recognizing test classes.
-
maven-surefire-plugin is normally used for unit tests and
recognizes class names such as *Test.java.
-
maven-failsafe-plugin is normally used for integration tests
and recognizes class names such as *IT.java.
The naming conventions are important because they allow the two plugins to
execute different groups of tests.
The following is a simple pom.xml configuration:
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>maven-tests-example</artifactId>
<version>1.0.0</version>
<properties>
<maven.compiler.release>8</maven.compiler.release>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.13.0</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.5.2</version>
</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>
</project>
The following diagram summarizes how the two plugins work:
Maven Project
|
|
src/test/java
|
+-----------+-----------+
| |
| |
UserServiceTest.java DatabaseIT.java
RepositoryTest.java JpaIT.java
| |
| |
v v
maven-surefire-plugin maven-failsafe-plugin
| |
v v
test phase integration-test phase
| |
+-----------+-----------+
|
v
verify phase
5 Package a Project
Example: Package a project
mvn clean package
This command compiles the code, runs the unit tests, and packages the
application into a distributable format such as a JAR or WAR.
Example: Run a Spring Web application
For example, assume you created a Spring Boot web application named
my-spring-webapp.
-
To compile the project and produce an artifact, run
mvn clean package from the project root.
-
To run the application, execute
java -jar target/my-spring-webapp-1.0.0.jar
from the project root.
The embedded Tomcat server starts on port 8080. Open your browser and go to
http://localhost:8080.
Example: Install to the local repository
mvn clean install
This is one of the most common Maven commands. It builds the project and
installs the generated artifact into your local repository, making it
available for other local projects.
Maven executes all default lifecycle phases up to install.
If Failsafe is configured, integration tests are also executed before the
artifact is installed.
Example: Deploy to a shared repository
mvn clean deploy
In a build environment, this command cleans, builds, tests, and deploys
artifacts to a remote repository. In multi-module projects, Maven processes
each submodule in order and deploys their artifacts.