Running Unit Tests With Maven
After we have finished this lesson, we
- Know how we can run our unit tests with Maven.
- Understand why we should categorize our tests by using JUnit 4 categories.
- Can run unit tests which use JUnit 4 categories.
Watch the Lesson
The text version of this lesson is given in the following:
Running Unit Tests With the Maven Surefire Plugin
We can run our unit tests by using the Maven Surefire plugin. The first thing that we have to do is to configure the Maven Surefire plugin in the build
section of our POM file. We can use the default configuration of this plugin by adding the following snippet into the build
section of our pom.xml file:
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <version>2.19.1</version> </plugin>
If we use the default configuration, the Maven Surefire plugin runs all test methods found from the test classes that fulfill these two conditions:
- The test classes must be found from the src/test/java directory.
- The name of the test class must start or end with the string: Test.
If our unit tests have resources such as property files or logging configuration files, we must put these resources to the src/test/resources directory.
Let’s write one unit test that writes the string: ‘The default configuration’ to System.out
. After we have written this unit test, the source code of our test class looks as follows:
import org.junit.Test; public class DefaultTest { @Test public void defaultTest() { System.out.println("The default configuration"); } }
We can now run our unit tests by running the following command at command prompt:
mvn clean test
If we don’t want to clean our build before we run our unit test, we have to use the command:
mvn test
When we run our unit tests, we notice that Maven runs our unit test:
------------------------------------------------------- T E S T S ------------------------------------------------------- Running com.testwithspring.starter.unittests.DefaultTest The default configuration Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.001 sec - in com.testwithspring.starter.unittests.DefaultTest Results : Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
If we write only unit tests, we don’t have to make any more changes to our POM file. However, quite often we also write integration and end-to-end tests. This means that we have to figure out a way to run our unit tests without running integration and end-to-end tests.
Configuring the Category of Our Unit Tests
By default, Maven doesnt’ differentiate unit, integration, and end-to-end tests. It runs all tests found from the test classes whose names start or end with the string: ‘Test’. We can solve this problem by using one of these two options:
- We can use different naming conventions for test classes that contain unit, integration, and end-to-end tests. The downside of this option is that we have to add an artificial suffix or prefix, which identifies the type of the test, to the name of our test class.
- We can use JUnit 4 categories. The downside of this option is that we have annotate each test class with the
@Category
annotation.
I argue that the option number two is a better choice because it doesn’t force us to add an artificial suffix or prefix to the name of our test classes. Also, the option number two gives us the possibility to create several subcategories inside one parent category and configure the tests that belong to these subcategories on class or method level.
For example, we can create two different categories for our integration tests. The tests that belong the category one are run in the local development environment, and the tests that belong to the category two are run in the CI server. This is useful if some of our integration tests are so slow that we don’t want to run them every time when we run our integration tests.
The lesson: Introduction to JUnit 4 Test Runners provides more information about JUnit 4 categories.
Let’s start by creating a new test class. The CategoryTest
class contains one unit test that writes the string: ‘The category: UnitTest’ to System.out
. Because we want to configure the category of this test class, we have to annotate it with the @Category
annotation.
The source code of our test class looks as follows:
import org.junit.Test; import org.junit.experimental.categories.Category; @Category(UnitTest.class) public class CategoryTest { @Test public void categoryTest() { System.out.println("The category: UnitTest"); } }
The UnitTest
interface is a marker interface which is used to identify our unit tests. Its source code looks as follows:
public interface UnitTest { }
After we have created our test class and configured its category, we have to ensure that the Maven Surefire Plugin runs all unit tests that belong to the UnitTest
category. We can specify the used category by setting the fully qualified class name of our category interface as the value of the groups
XML element.
After we have configured the used category, the configuration of the Surefire Maven plugin looks as follows:
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <version>2.19.1</version> <configuration> <groups>com.testwithspring.starter.unittests.UnitTest</groups> </configuration> </plugin>
When we run our unit tests, we notice that Maven runs only the test found from the CategoryTest
class and ignores the test found from the DefaultTest
class:
------------------------------------------------------- T E S T S ------------------------------------------------------- Running com.testwithspring.starter.unittests.CategoryTest The category: UnitTest Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.001 sec - in com.testwithspring.starter.unittests.CategoryTest Results : Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
Let’s summarize what we learned from this lesson.
Summary
This lesson has taught us three things:
- We can run unit tests by using the Maven Surefire plugin.
- By default, Maven doesn’t differentiate unit, integration, and end-to-end tests.
- We should categorize our tests by using JUnit 4 categories.