image blog the correct way to use integration tests in your build process
June 7, 2023

How to Use Java Integration Testing

Java Testing
Java Application Development

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: 

Back to top

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 top

Java 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:

  1. Developers run the test goal during development
  2. Developers run the test goal before any commit
  3. Developers run the integration-test goal before a major commit with many side effects
  4. Build server compiles code and runs the test goal every 15-30 minutes (main build)
  5. Build server compiles code and runs the integration-test goal every day (integration build)
  6. 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 top

Java 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

Curious about what your Java development peers are using in their Java tech stack? Find out in the 2023 Java Developer Productivity Report. 

Download Now

Back to top

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. 

Try Free

This blog post was originally published in April 2013 and has been edited for clarity and relevancy. 

Back to top