
How to Use Java Integration Testing
Unit testing can be used to mock all the dependencies of a single Java class in order to isolate it from the rest of the system. This way the class under test is in a controlled environment where you can test its own business logic with nothing else in the way. There are times, however, when you should not use mocking during testing. For these cases, you need Java integration testing. Read on to learn:
What is a Java Integration Test?
While there is no hard and fast definition, a Java integration test generally:
- Uses the database
- Uses the network
- Uses an external system (e.g., a queue or a mail server)
- Reads/writes files or performs other I/O
Sometimes, there isn’t a clear distinction between an integration test and a unit test. A basic rule of thumb is that a test meets the following criteria:
- A test uses the database
- A test uses the network
- Uses an external system (e.g. a queue or a mail server)
- Reads/writes files or performs other I/O
Unit Test vs. Integration Test
The chart below breaks down the differences between Java unit tests versus integration tests.
Unit test | Integration test |
---|---|
Results depends only on Java code | Results also depends on external systems |
Easy to write and verify | Setup of integration test might be complicated |
A single class/unit is tested in isolation | One or more components are tested |
All dependencies are mocked if needed | No mocking is used (or only unrelated components are mocked) |
Test verifies only implementation of code | Test verifies implementation of individual components and their interconnection behaviour when they are used together |
A unit test uses only JUnit/TestNG and a mocking framework | An integration test can use real containers and real DBs as well as special java integration testing frameworks (e.g. Arquillian or DbUnit) |
Mostly used by developers | Integration tests are also useful to QA, DevOps, Help Desk |
A failed unit test is always a regression (if the business has not changed) | A failed integration test can also mean that the code is still correct but the environment has changed |
Unit tests in an Enterprise application should last about 5 minutes | Integration tests in an Enterprise application can last for hours |
When to Use Java Integration Testing
Java integration testing should be used when you are interested in the interface of this class with its dependencies. By doing so, you zoom out from a single class to testing a component of the system. This is appropriate if the system is built on multiple classes or uses other systems, e.g., a database or a queue.
Back to topJava Integration Testing Best Practices
While there may not be a hard-and-fast definition for what comprises a Java integration test, there are best practices for implementing them and what to do if and when they fail.
1. Use Detailed Logging
The use of detailed logging must be accounted for when conducting Java integration tests. When a unit test fails it is very easy to understand why since the scope is very narrow. When an integration test fails it’s often not so simple. Because an integration test by definition is based on many components and a specific data flow, identifying the failure cause is not always straightforward. Using detailed logging statements can help alleviate this problem. They’re always needed in an Enterprise application regardless of unit tests. This way, when an integration test fails you can examine the logs and understand if the issue is in the code or in an external resource used by the test.
2. Don't Use Java Integration Testing and Unit Testing Concurrently
This is the most important aspect of unit tests. In a large enterprise application, integration and unit tests must be handled differently. Here’s an all-too-common scenario: New developers simply declare that “writing unit tests is a waste of time.” They’re right from their point of view, since nobody wants to work with a broken test suite, but this is a situation that needs to be avoided.
3. Split Unit and Integration Tests
There are many ways to split unit and integration tests, including using the Maven failsafe plugin. Unit tests should follow the naming convention introduced in the first part of this series. Unit test classes are named with “name of class + Test”. Then they are placed in the test directory of the Maven project structure. The unit tests are executed automatically when the test goal is run. Next you should add the failsafe plugin in your pom.xml file.
…
…
org.apache.maven.plugins
maven-failsafe-plugin
2.13
integration-test
integration-test
verify
verify
Your integration tests have a different naming convention, however. They are named as “name of class + IT”. IT stands for Integration Test. Now the test goal will ignore them. Instead these tests will be executed by the integration-test goal which is a built-in goal into Maven. Below is a table that summarizes this split.
Unit tests | Integration Tests | |
---|---|---|
Located in | Maven test directory | Maven test directory |
Naming convention | name of class + Test | name of class + IT |
Example class name | BasketWeightTest.java | InvoicingProcessorIT.java |
Managed by | Maven surefire plugin | Maven failsafe plugin |
Executed in test goal | Yes | No |
Executed in integration-test goal | No | Yes |
How to Run Integration Tests in Your Build Process
Now that all these changes are done, you have great flexibility on how you run unit tests. Most importantly, your build server (e.g. Jenkins) should contain a mixture of jobs that deal with both kinds of tests. Here is a overview of suggested jobs.
Job type | Schedule | Description | Tests |
---|---|---|---|
Main build | Every 15 minutes or half hour. | Only compiles and runs unit tests. Should finish in 15-20 minutes max | Only unit tests |
Integration build | Every 24 hours (usually at night) | Runs integrations tests. Can run for 2-3 hours | All tests |
QA build | Manually | Deploys to a QA environment | All tests |
The suggested workflow is the following:
- Developers run the test goal during development
- Developers run the test goal before any commit
- Developers run the integration-test goal before a major commit with many side effects
- Build server compiles code and runs the test goal every 15-30 minutes (main build)
- Build server compiles code and runs the integration-test goal every day (integration build)
- Build server compiles code and runs the integration-test goal before a release to QA
With this workflow it is clear that developers get fast feedback from the unit tests so anything that breaks can be fixed immediately. The boring process of running integration tests is left to the build server which runs them automatically in a well defined schedule.
Back to topJava Integration Testing Frameworks
As we mentioned at the beginning of the article, developers often utilize a Java integration testing framework. A few of the more popular Java integration testing frameworks include Arquillian, DbUnit, and JUnit
- Arquillian - a Java integration testing framework specific to Java EE
- DbUnit - as the name implies, DbUnit can run both unit and integration tests
- JUnit - while most use JUnit for unit testing, many use JUnit for integration testing
Back to topCurious about what your Java development peers are using in their Java tech stack? Find out in the 2023 Java Developer Productivity Report.
Final Thoughts
Implementing Java integration testing can save your organization development time. Compound those time efficiency savings by eliminating rebuilds and redeploys with JRebel and save upwards of a month of development time annually.
Discover how much Java development time you could save during your 14-day free trial of JRebel.
This blog post was originally published in April 2013 and has been edited for clarity and relevancy.
Back to top