Spring Boot @DataJpaTest Annotation | Unit Testing Spring Data JPA Repositories

🚀 Introduction: What is @DataJpaTest in Spring Boot?

The @DataJpaTest annotation in Spring Boot is used for unit testing JPA repositories. It loads only the repository layer, providing an isolated database environment for testing CRUD operations.

Key Features of @DataJpaTest:
✔ Loads only JPA-related components (repositories, entities, and configurations).
✔ Uses an in-memory database (H2 by default) for testing.
✔ Rolls back transactions after each test to maintain data integrity.
✔ Supports SQL schema initialization (schema.sql, data.sql).

📌 In this guide, you’ll learn:
How @DataJpaTest works in Spring Boot.
How to use it for unit testing repositories.
Best practices for writing database tests.

1️⃣ Difference Between @DataJpaTest and @SpringBootTest

Annotation Purpose Components Loaded
@DataJpaTest Unit testing repositories Repositories, Entities, DataSource, Hibernate, TransactionManager
@SpringBootTest Full application testing Entire Spring Context (Controllers, Services, Repositories, etc.)

📌 When to Use @DataJpaTest?
✔ When testing only the repository layer (unit tests).
✔ When using in-memory databases (H2, HSQL, Derby) for fast tests.
✔ When verifying database operations like save, update, delete, and queries.

2️⃣ Basic Example: Testing a Repository with @DataJpaTest

📌 Example: Testing UserRepository for Basic CRUD Operations

1. Entity (User.java)

@Entity
@Table(name = "users")
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;
    private String email;

    // Constructors, Getters, and Setters
}

2. Repository (UserRepository.java)

public interface UserRepository extends JpaRepository<User, Long> {
    Optional<User> findByEmail(String email);
}

3. Test Class (UserRepositoryTest.java)

@DataJpaTest
class UserRepositoryTest {

    @Autowired
    private UserRepository userRepository;

    @Test
    void testSaveUser() {
        User user = new User(null, "Ramesh", "ramesh@example.com");
        User savedUser = userRepository.save(user);

        assertNotNull(savedUser.getId());
        assertEquals("Ramesh", savedUser.getName());
    }

    @Test
    void testFindByEmail() {
        User user = new User(null, "Suresh", "suresh@example.com");
        userRepository.save(user);

        Optional<User> foundUser = userRepository.findByEmail("suresh@example.com");
        assertTrue(foundUser.isPresent());
        assertEquals("Suresh", foundUser.get().getName());
    }
}

📌 Test Output:

Test passed ✅

The database is automatically reset after each test due to transaction rollback.

3️⃣ Using @TestEntityManager for Advanced Database Operations

Spring Boot provides TestEntityManager, a wrapper around JPA’s EntityManager, for more fine-grained control over database operations.

📌 Example: Using TestEntityManager for Manual Persisting

1. Test Class with TestEntityManager

@DataJpaTest
class UserRepositoryTest {

    @Autowired
    private TestEntityManager entityManager;

    @Autowired
    private UserRepository userRepository;

    @Test
    void testFindById() {
        User user = new User(null, "John", "john@example.com");
        User savedUser = entityManager.persistFlushFind(user);

        Optional<User> foundUser = userRepository.findById(savedUser.getId());

        assertTrue(foundUser.isPresent());
        assertEquals("John", foundUser.get().getName());
    }
}

TestEntityManager allows manually persisting and flushing data before testing queries.

4️⃣ Using @Sql to Load Test Data

Spring Boot allows using SQL scripts to prepopulate test data before running tests.

📌 Example: Loading Initial Data from SQL File

1. data.sql File (Inside src/test/resources)

INSERT INTO users (id, name, email) VALUES (1, 'Amit', 'amit@example.com');
INSERT INTO users (id, name, email) VALUES (2, 'Raj', 'raj@example.com');

2. Test Class with @Sql

@DataJpaTest
@Sql("/data.sql") // Load test data before running tests
class UserRepositoryTest {

    @Autowired
    private UserRepository userRepository;

    @Test
    void testFindAllUsers() {
        List<User> users = userRepository.findAll();
        assertEquals(2, users.size());
    }
}

Ensures a consistent dataset for tests.

5️⃣ Using @Rollback(false) to Persist Data Between Tests

By default, @DataJpaTest rolls back transactions after each test. Use @Rollback(false) if you want to keep data for multiple tests.

📌 Example: Disabling Rollback for a Test

@DataJpaTest
class UserRepositoryTest {

    @Autowired
    private UserRepository userRepository;

    @Test
    @Rollback(false) // Prevent rollback
    void testSaveUser() {
        User user = new User(null, "Karan", "karan@example.com");
        userRepository.save(user);
    }

    @Test
    void testUserExists() {
        List<User> users = userRepository.findAll();
        assertFalse(users.isEmpty()); // Should be true if @Rollback(false) is set
    }
}

Useful when multiple tests depend on persistent data.

6️⃣ Configuring @DataJpaTest with a Real Database (Instead of H2)

By default, @DataJpaTest uses an in-memory H2 database. To use a real database (MySQL, PostgreSQL, etc.), disable automatic database replacement.

📌 Example: Using MySQL Instead of H2

@DataJpaTest
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
class UserRepositoryTest {
    // Test with actual MySQL/PostgreSQL database
}

Useful for integration testing with real database schema.

🎯 Summary: Best Practices for Using @DataJpaTest

Use @DataJpaTest for unit testing repositories, not full application testing.
Use @MockBean for services if needed (@DataJpaTest does not load services).
Use @Sql to preload test data for consistency.
Use @Rollback(false) if multiple tests depend on saved data.
Use @AutoConfigureTestDatabase(replace = NONE) to test with real databases.
Use TestEntityManager for advanced database operations.

🚀 Following these best practices ensures reliable, maintainable database tests in Spring Boot!

Comments

Spring Boot 3 Paid Course Published for Free
on my Java Guides YouTube Channel

Subscribe to my YouTube Channel (165K+ subscribers):
Java Guides Channel

Top 10 My Udemy Courses with Huge Discount:
Udemy Courses - Ramesh Fadatare