Configuring Separate Spring DataSource for Tests

1. Overview

When testing a Spring application that relies on a persistence layer, such as JPA, we may want to set up a test data source to use a smaller, faster database – one that is different from the one we use to run the application – in order to make running our tests much easier.

Configuring a data source in Spring requires defining a bean of type DataSource, either manually or, if using Spring Boot, through standard application properties.

In this quick tutorial, we’re going to take a look at several ways to configure a separate data source for testing in Spring.

2. Maven Dependencies

We are going to create a Spring Boot application using Spring JPA and testing, so we will need the following dependencies:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
    <version>2.1.3.RELEASE</version>
</dependency>
<dependency>
    <groupId>com.h2database</groupId>
    <artifactId>h2</artifactId>
    <version>1.4.197</version>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <version>2.1.3.RELEASE</version>
</dependency>

The latest versions of spring-boot-starter-data-jpa, h2 and spring-boot-starter-test can be downloaded from Maven Central.

Let’s take a look at a few different ways to configure a DataSource for testing.

3. Using a Standard Properties File in Spring Boot

The standard properties file that Spring Boot picks up automatically when running an application is called application.properties and resides in the src/main/resources folder.

If we want to use different properties for tests, then we can override the properties file in the main folder by placing another file with the same name in src/test/resources.

The application.properties file in src/test/resources folder should contain the standard key-value pairs necessary for configuring a data source. These properties are prefixed with spring.datasource.

For example, let’s configure an H2 in-memory database as a data source for tests:

spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.url=jdbc:h2:mem:db;DB_CLOSE_DELAY=-1
spring.datasource.username=sa
spring.datasource.password=sa

Spring Boot will use these properties to automatically configure a DataSource bean.

Let’s define a very simple GenericEntity and repository using Spring JPA:

@Entity
public class GenericEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    private String value;

    //standard constructors, getters, setters
}
public interface GenericEntityRepository
  extends JpaRepository<GenericEntity, Long> { }

Next, let’s write a JUnit test for the repository. In order for a test in a Spring Boot application to pick up the standard data source properties we have defined, it has to be annotated with @SpringBootTest:

@RunWith(SpringRunner.class)
@SpringBootTest(classes = Application.class)
public class SpringBootJPAIntegrationTest {

    @Autowired
    private GenericEntityRepository genericEntityRepository;

    @Test
    public void givenGenericEntityRepository_whenSaveAndRetreiveEntity_thenOK() {
        GenericEntity genericEntity = genericEntityRepository
          .save(new GenericEntity("test"));
        GenericEntity foundEntity = genericEntityRepository
          .findOne(genericEntity.getId());

        assertNotNull(foundEntity);
        assertEquals(genericEntity.getValue(), foundEntity.getValue());
    }
}

4. Using a Custom Properties File

If we don’t want to use the standard application.properties file and keys, or if we’re not using Spring Boot, we can define a custom .properties file with custom keys, then read this file in a @Configuration class to create a DataSource bean based on the values it contains.

This file will be placed in src/main/resources folder for the normal running mode of the application, and in src/test/resources in order to be picked up by tests.

Let’s create a file called persistence-generic-entity.properties that uses an H2 in-memory database for tests and place it in the src/test/resources folder:

jdbc.driverClassName=org.h2.Driver
jdbc.url=jdbc:h2:mem:db;DB_CLOSE_DELAY=-1
jdbc.username=sa
jdbc.password=sa

Next, we can define the DataSource bean based on these properties in a @Configuration class that loads our persistence-generic-entity.properties as a property source:

@Configuration
@EnableJpaRepositories(basePackages = "org.baeldung.repository")
@PropertySource("persistence-generic-entity.properties")
@EnableTransactionManagement
public class H2JpaConfig {
    // ...
}

For a more detailed example of this configuration, please take a look at our previous article on Self-contained testing with an in-memory database, section “JPA Configuration”.

Then, we can create a JUnit test similar to the previous one, except it will load our configuration class:

@RunWith(SpringRunner.class)
@SpringBootTest(classes = {Application.class, H2JpaConfig.class})
public class SpringBootH2IntegrationTest {
    // ...
}

5. Using Spring Profiles

Another way we could configure a separate DataSource for testing is by leveraging Spring Profiles to define a DataSource bean that is only available in a test profile.

For this, we can use a .properties file as before, or we can write the values in the class itself.

Let’s define a DataSource bean for the test profile in a @Configuration class that will be loaded by our test:

@Configuration
@EnableJpaRepositories(basePackages = {
  "org.baeldung.repository",
  "org.baeldung.boot.repository"
})
@EnableTransactionManagement
public class H2TestProfileJPAConfig {

    @Bean
    @Profile("test")
    public DataSource dataSource() {
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName("org.h2.Driver");
        dataSource.setUrl("jdbc:h2:mem:db;DB_CLOSE_DELAY=-1");
        dataSource.setUsername("sa");
        dataSource.setPassword("sa");

        return dataSource;
    }

    // configure entityManagerFactory
    // configure transactionManager
    // configure additional Hibernate properties
}

Then, in the JUnit test class, we need to specify that we want to use the test profile by adding the @ActiveProfiles annotation:

@RunWith(SpringRunner.class)
@SpringBootTest(classes = {
  Application.class,
  H2TestProfileJPAConfig.class})
@ActiveProfiles("test")
public class SpringBootProfileIntegrationTest {
    // ...
}

6. Conclusion

In this quick tutorial, we’ve seen several ways in which we can configure a separate DataSource for testing in Spring.

As always, the full source code of the examples can be found over on GitHub.

Leave a Reply

Your email address will not be published.