Integration Testing with Spring and JUnit

Integration Testing with Spring and JUnit

6 Comments

You will find a greater need for Integration tests as your testing requirements become more complex when you’re supporting enterprise application development using the Spring Framework. Sometimes, allowing Spring to manage the beans makes your testing easier, sometimes you want to test parts of your Spring Configuration, sometimes you’ll need to wire in a Mock component for your tests.

Spring and JUnit are a powerful combination. You can easily bring in a custom Spring configuration to meet the needs of your test scenario.

Spring Configuration

There are a number of different ways to create Spring Beans. In this example, I’m going to use a Java configuration. Below is my Spring Configuration class for our integration test.

ProductServiceTestConfig

Note the use of the annotation @Configuration  at the top of the class. This designates the class as a Spring Configuration class. The annotation @Bean  tells Spring to use this method to load a Spring bean into the context. The default behavior of Spring is to use the name of the method as the bean name. This behavior is easily overridden by passing a name to the bean annotation as @Bean(name = "customBeanName"). In this configuration class, I’m defining two spring beans. The same test stub bean we used in the previous unit test example and the product service implementation. Notice that I do not manage the injection of the repository bean into the service bean. I allow the Spring Framework to manage the dependency injection.

package guru.springframework.test.config;

import guru.springframework.repositories.ProductRepository;
import guru.springframework.repositories.ProductRepositoryTestStub;
import guru.springframework.services.ProductService;
import guru.springframework.services.ProductServiceImpl;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class ProductServiceTestConfig {
    @Bean
    ProductRepository productRepository(){
        return new ProductRepositoryTestStub();
    }

    @Bean
    ProductService productService(){
        return new ProductServiceImpl();
    }
}

 

Spring and JUnit Configuration

To support Spring and JUnit, we need to add two new annotations to our test class. The first annotation is @RunWith(SpringJUnit4ClassRunner.class) . The annotation is provided by the JUnit team, which is an API to allow for the extension of JUnit to allow for a customized test runner class. Within this annotation, we’re passing in the class SpringJUnit4ClassRunner.class , this is the test runner class supplied by the Spring Framework. This custom test runner is what enables the Spring Context. Your test class in effect becomes a Spring Bean, and is managed in the Spring context. The second annotation we need to use is @ContextConfiguration, this allows us to specify the configuration for the Spring Context. The configuration of this annotation is very versatile. As the complexity of your application grows, so will your configuration. For our example today, our needs are not very complex. I only have one configuration class to bring into the Spring Context. I can do this simply by passing the class name to the annotation using the classes property like: @ContextConfiguration(classes = {ProductServiceTestConfig.class}). Through the use of these two annotations, when I run the JUnit test, the Spring Context will be started and the beans we’ve specified in the configuration will be available for use in our test.

JUnit Test

By convention, I’m naming my Integration Test with the suffix of ‘IT’. Traditionally, you will name your unit tests with the suffix of ‘Test’ or ‘Tests’, and your integration tests with the suffix of ‘IT’. This does not affect how JUnit runs the tests. But it does have ramifications later when building with tools such as Maven and deploying and reporting from Continuous Build servers such as Jenkins.

ProductServiceImplIt

The class below is the same test we looked at above as a Unit test, but now it’s an Integration test, and we are using Spring to manage the dependency injection. Here we have the test class annotated with the annotations we just discussed above. Since the class is now managed by Spring, we can use the @Autowired annotation to inject our service bean into the test. This bean is a Spring Bean, which is configured and managed by Spring. Thus it will have the repository injected for us as we specified in our test configuration class.

package guru.springframework.services;

import guru.springframework.domain.Product;
import guru.springframework.test.config.ProductServiceTestConfig;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import static org.junit.Assert.assertEquals;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {ProductServiceTestConfig.class})
public class ProductServiceImplIT {
    private ProductService productService;

    @Autowired
    public void setProductService(ProductService productService) {
        this.productService = productService;
    }

    @Test
    public void testGetProduct(){
        Product product = productService.getProduct(1L);
        assertEquals(product.getDescription(), "This is a test product");
    }
}

 

Free Introduction to Spring Tutorial

Are you new to the Spring Framework? Checkout my Free Introduction to Spring Online Tutorial.

 

About jt

    You May Also Like

    6 comments on “Integration Testing with Spring and JUnit

    1. February 12, 2017 at 9:01 am

      Can you tell me why this is different from a unit test of the method? You used a mock repository so where is the Integration? I thought it woukd involve using mock mvc to hit the controller to the service to the real repository bur with a mocked database using in memory or similsr? I’m confused as the project I’m on had these as unit tests and the IT tests fire against the running Web app. I’m quite new to spring so trying to read up.

      Reply
    2. February 13, 2017 at 8:52 am

      Its considered an integration test because I’m using the Spring context to manage an inject beans into the test class.

      Reply
    3. February 20, 2017 at 9:34 am

      Do you have more examples on JUNIT and Mockito ?

      Reply
    4. August 2, 2019 at 2:24 am

      Hi, I read your all JUnit tutorial.
      I conclude that all you provided is totally time waste.

      Reply
      • November 27, 2019 at 6:01 pm

        What a douche.. these tutorials are some of the best, well-described on the net/

        Reply

    Leave a Reply

    Your email address will not be published. Required fields are marked *

    This site uses Akismet to reduce spam. Learn how your comment data is processed.