In our previous tutorial, we implemented the soft delete functionality for the user entity and wrote a JUnit test to test the persistent layer. In this tutorial, we are gonna understand how the @DataJpaTest
can be used for various scenarios to test the persistence layer.
Introduction
@DataJpaTest
focuses only on JPA components. Using this annotation will disable full auto-configuration and instead apply only configuration relevant to JPA tests.
By default,
- It scans for
@Entity
classes and configures Spring Data JPA repositories. If an embedded database is available on the classpath, it configures one as well replacing any explicit or usually auto-configuredDataSource
. - Tests annotated with
@DataJpaTest
are transactional and roll back at the end of each test. If you want to override these settings, then use the@AutoConfigureTestDatabase
annotation. - SQL queries are logged by setting the
spring.jpa.show-sql
property totrue
. You can disable this using theshowSql
attribute.
If you are looking to load your full application configuration, but use an embedded database, you should consider @SpringBootTest
combined with @AutoConfigureTestDatabase
rather than this annotation.
When using JUnit 4, this annotation should be used in combination with @RunWith(SpringRunner.class)
.
Test with Embedded In-memory Database
As described earlier, @DataJpaTest
will try to configure an embedded database that is available in the classpath by default. This means we need to include the dependency of any one of the embedded databases in our pom.xml
. Otherwise, we will end up with the following error:
Caused by: java.lang.IllegalStateException: Failed to replace DataSource with an embedded database for tests. If you want an embedded database please put a supported one on the classpath or tune the replace attribute of @AutoConfigureTestDatabase.
Once we add an embedded database dependency like h2 in our pom.xml
, then we can use the @DataJpaTest
annotation to run the tests on the embedded in-memory h2 database.
@DataJpaTest
class UserRepositoryTest {
@Autowired
private UserRepository userRepository;
@Autowired
private RoleRepository roleRepository;
@Test
void testSoftDelete() {
// Add a new user
User user = new User();
user.setDisplayName("Chinna");
user.setEmail("[email protected]");
// Add a role to the user
Role adminRole = roleRepository.findByName(Role.ROLE_ADMIN);
user.addRole(roleRepository.findByName(Role.ROLE_USER));
user.addRole(adminRole);
user = userRepository.saveAndFlush(user);
assertEquals(2, user.getRoles().size());
}
}
Test with Real Database
When we want to run the tests with the real database, then we need to use the @AutoConfigureTestDatabase
annotation with replace
attribute set to Replace.NONE
. This configuration instructs Spring Boot not to replace the application default DataSource
.
@DataJpaTest
@AutoConfigureTestDatabase(replace = Replace.NONE)
class UserRepositoryTest {
Note: In this scenario, we don’t need to include the dependency of embedded database in the
pom.xml
since the real datasource will not be replaced with test database.
Test with Auto Configured Test Database
In some scenarios, we may want to customize the test data source configuration as we did in our previous tutorial. In such scenarios, we need to perform the following steps. Let’s assume that we are gonna use the h2 in-memory database for our tests.
Step 1: Add the Database Dependency
Add the h2 database dependency into pom.xml
pom.xml
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
Step 2: Define Database Connection Properties
Define h2 database connection properties in src/test/resources/application.properties
src/test/resources/application.properties
#Test Properties
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.url=jdbc:h2:mem:db;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE;MODE=MySQL;NON_KEYWORDS=USER
spring.datasource.username=sa
spring.datasource.password=sa
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.H2Dialect
spring.jpa.hibernate.ddl-auto=create-drop
spring.jpa.show-sql=true
Note: Here, we have created the
application.properties
file in thesrc/test/resources
directory which will be picked up automatically for auto configuring the test database while executing the JUnit tests. Hence, you don’t need to specify any profile specific properties and activate that profile in the JUnit tests.
Step 3: Use @DataJpaTest with @AutoConfigureTestDatabase
Now, we can write the JUnit tests and run them on the AutoConfigured test database.
@DataJpaTest
@AutoConfigureTestDatabase(replace = Replace.NONE)
class UserRepositoryTest {
Note: If you configure the test datasource in a properties file and try to load it with
@TestPropertySource(locations = "classpath:test-database.properties")
, then@DataJpaTest
will not load those properties unless untill you specify@AutoConfigureTestDatabase(replace = Replace.NONE)
Test with Embedded DERBY Database
Apache Derby, an Apache DB subproject, is an open source relational database implemented entirely in Java. If you want to use this one for JUnit tests, then add the following dependency
<dependency>
<groupId>org.apache.derby</groupId>
<artifactId>derby</artifactId>
<scope>runtime</scope>
</dependency>
And use @AutoConfigureTestDatabase
annotation with connection
attribute set to EmbeddedDatabaseConnection.DERBY
@DataJpaTest
@AutoConfigureTestDatabase(connection = EmbeddedDatabaseConnection.DERBY)
class UserRepositoryTest {
Note: You don’t have to use
AutoConfigureTestDatabase
to explicitly specify the database connection type if you have only one embedded databse dependency in thepom.xml
. i.e., in the classpath.
Test with Embedded H2 Database
H2 is an open source relational database written in Java. If you want to use this one for JUnit tests, then add the following dependency.
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
And use @AutoConfigureTestDatabase
annotation with connection
attribute set to EmbeddedDatabaseConnection.H2
@DataJpaTest
@AutoConfigureTestDatabase(connection = EmbeddedDatabaseConnection.H2)
class UserRepositoryTest {
Test with Embedded HSQLDB Database
HSQLDB is an open source relational database written in Java. If you want to use this one for JUnit tests, then add the following dependency.
<dependency>
<groupId>org.hsqldb</groupId>
<artifactId>hsqldb</artifactId>
<scope>runtime</scope>
</dependency>
And use @AutoConfigureTestDatabase
annotation with connection
attribute set to EmbeddedDatabaseConnection.HSQLDB
@DataJpaTest
@AutoConfigureTestDatabase(connection = EmbeddedDatabaseConnection.HSQLDB)
class UserRepositoryTest {
Test with TestEntityManager
Data JPA tests may also inject a TestEntityManager
bean, which provides an alternative to the standard JPA EntityManager
that is specifically designed for tests.
@DataJpaTest
@AutoConfigureTestDatabase(replace = Replace.NONE)
class UserRepositoryTest {
@Autowired
private TestEntityManager entityManager;
@Test
void testSoftDelete() {
// Add a new user
User user = new User();
user.setDisplayName("Chinna");
user.setEmail("[email protected]");
user = this.entityManager.persistAndFlush(user);
assertEquals("Chinna", user.getDisplayName());
}
}
Conclusion
That’s all folks. In this article, we have explored various scenarios for testing the DAO layer using Spring Boot DataJpaTest
annotation.
Thank you for reading.