🎓 Top 15 Udemy Courses (80-90% Discount): My Udemy Courses - Ramesh Fadatare — All my Udemy courses are real-time and project oriented courses.
▶️ Subscribe to My YouTube Channel (178K+ subscribers): Java Guides on YouTube
▶️ For AI, ChatGPT, Web, Tech, and Generative AI, subscribe to another channel: Ramesh Fadatare on YouTube
🚀 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
Post a Comment
Leave Comment