1. INTRODUCTION

Generally, when you write Java unit tests, you stub data or mock the target class dependencies. This allows you to verify the business logic in an environment where you don’t depend on third party services.

Integration tests also play an important role in the Continuous Integration / Delivery (CI/CD) process to release software frequent and safe. As I have mentioned before, integration testing goal is to verify that interaction between different parts of the system work well. Examples of such interactions are:

• Connecting to a RDBMS to retrieve or persist data
• Consuming a message from a broker
• Sending an email
• Processing an upstream response

In large Enterprise applications development, with hundreds of unit and integration tests, the test suites take a considerable amount of time to complete, normally hours.

Wouldn’t it make sense to split the tests by their purpose and execution speed? It would be beneficial for an organization to get a quicker feedback when tests fail.

It would then be advisable to implement a fail-fast approach and break the build process when unit tests fail. This post covers configuring Maven’s maven-surefire-plugin to split running unit and integration tests.

• Java 7+.
• Maven 3.2+.

3. THE REST CONTROLLER, UNIT AND INTEGRATION TESTS

Assuming you have generated a Spring Boot 2 application using Spring Initializr, from command line or via your preferred IDE, let’s add a simple REST controller DemoController.java:

Let’s now add the unit and integration test classes meant to run during Maven’s test and integration-test phases.

DemoControllerTest.java:

DemoControllerIT.java:

4. CONFIGURING maven-surefire-plugin

There are now two unit test classes, DemoControllerTest.java and DefaultSomeBusinessServiceTest and two integration tests, DemoControllerIT.java and ApplicationTests. Let’s configure maven-surefire-plugin in pom.xml to split running them in the test and integration-test phases:

5. RUNNING THE TESTS AND BUILDING THE ARTIFACTS

5.1. A SUCCESSFUL BUILD

Let’s first run and analyze a successful build:

The verify phase also executes the test, package and integration-test phases among others. Read more at Maven’s Build Default Lifecycle Reference.

During the test phase execution, maven-surefire-plugin’s default-test execution was skipped. That’s the result of setting skipTests to true in pom.xml (lines 5 through 7). The unit-tests execution ran one test in each Test-suffixed class without failure.

Next the package phase ran and built the main artifact. Then spring-boot-maven-plugin replaced the main jar with an uber jar containing all the dependencies this application needs.

The integration-test phase ran right after. This time Maven runs test methods found in DemoControllerIT.java and ApplicationTests classes, ending in a successful build.

Let’s take a look at Maven’s target folder:

Notice the Maven Surefire reports. Stay tuned, I’ll cover uploading these reports and code coverage using JaCoCo to SonarQube in another post; without running the tests twice as I have seen happening when using Cobertura.

5.2. WHEN UNIT TESTS FAIL

Let’s cause a unit test to fail in DemoControllerTest.java as a second scenario:

And attempting to build again:

The test phase failed and prevented the build from running following phases. It’s a fail-fast approach. The artifact wasn’t built and integration tests didn’t run. Read more at Maven’s Build Default Lifecycle Reference.

6. CONCLUSION

It’s a good practice to add unit and integration tests when developing Enterprise applications. While a unit test suite should run in the order of milliseconds or seconds, integration tests take minutes if not hours.

Reseeding data, network traffic, starting Docker containers before executing a test or test suite will slow down your integration tests. It would make sense to split them when your test suites are large enough to have a faster feedback. Why? With a shorter build cycle, you get quicker feedback, allowing you to act faster, increasing your productivity.