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 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. We can do this either manually, or if using Spring Boot, through standard application properties.

In this quick tutorial, we’ll learn several ways to configure a separate data source for testing in Spring.

2. Maven Dependencies

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

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

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

Now let’s 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. It resides in the src/main/resources folder.

If we want to use different properties for tests, 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 the 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 defined, we have to annotate it 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 the 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, we can read through the section “JPA Configuration” in our previous article on Self-contained testing with an in-memory database.

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

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

5. Using Spring Profiles

Another way we can configure a separate DataSource for testing is by leveraging Spring Profiles to define a DataSource bean that’s 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 brief article, we explored several ways to configure a separate DataSource for testing in Spring.

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