Spring Boot @DataJpaTest Example

1. Introduction

1. @DataJpaTest is used for testing the repository layer in isolation.

2. It configures an in-memory database by default, making it ideal for lightweight data access tests.

3. The annotation ensures that each test is transactional and rolls back after completion.

2. Implementation Steps

1. Set up a Spring Boot project with spring-boot-starter-data-jpa and h2 as the in-memory database.

2. Create an @Entity class to represent the data model.

3. Define a repository interface extending JpaRepository for CRUD operations.

4. Write a test class annotated with @DataJpaTest to test repository operations.

5. Utilize TestEntityManager for persisting and finding entities within test methods.

6. Execute CRUD operation tests and verify the results using assertions.

3. Implementation Example

// Step 2: Define an entity class
@Entity
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    private String name;
    private String email;
    // Standard getters and setters
}

// Step 3: Define a repository interface
public interface UserRepository extends JpaRepository<User, Long> {
    User findByName(String name);
}

// Step 4: Write a test class with @DataJpaTest for repository testing
@DataJpaTest
public class UserRepositoryTest {

    @Autowired
    private TestEntityManager entityManager;

    @Autowired
    private UserRepository userRepository;

    // Test for Create operation
    @Test
    public void whenSaved_thenFindsByName() {
        User user = new User();
        user.setName("John");
        user.setEmail("john@example.com");
        entityManager.persist(user);

        User foundUser = userRepository.findByName("John");
        assertNotNull(foundUser);
        assertEquals(user.getName(), foundUser.getName());
    }

    // Test for Read operation
    @Test
    public void whenFoundById_thenCorrect() {
        User user = new User();
        user.setName("Anna");
        user.setEmail("anna@example.com");
        entityManager.persist(user);
        entityManager.flush();

        User foundUser = userRepository.findById(user.getId()).orElse(null);
        assertNotNull(foundUser);
        assertEquals(user.getName(), foundUser.getName());
    }

    // Test for Update operation
    @Test
    public void whenUpdated_thenCorrect() {
        User user = new User();
        user.setName("Tom");
        user.setEmail("tom@example.com");
        entityManager.persist(user);

        User foundUser = userRepository.findByName("Tom");
        foundUser.setEmail("tommy@example.com");
        userRepository.save(foundUser);

        User updatedUser = userRepository.findByName("Tom");
        assertEquals("tommy@example.com", updatedUser.getEmail());
    }

    // Test for Delete operation
    @Test
    public void whenDeleted_thenNotFound() {
        User user = new User();
        user.setName("Bob");
        user.setEmail("bob@example.com");
        entityManager.persist(user);
        entityManager.flush();

        userRepository.delete(user);

        User deletedUser = userRepository.findByName("Bob");
        assertNull(deletedUser);
    }
}

// Step 6: Execute the test class
// The tests can be executed through the IDE or using the Maven command: mvn test

Output:

// Expected console output showing the result of the test execution
Tests run: 4, Failures: 0, Errors: 0, Skipped: 0

Explanation:

1. User is an entity class representing the user table in the database.

2. UserRepository extends JpaRepository, providing CRUD operations without the need for an implementation.

3. UserRepositoryTest contains various methods to test CRUD operations, each marked with @Test.

4. TestEntityManager is used to set up and manipulate test data directly in the tests.

5. The test methods whenSaved_thenFindsByName, whenFoundById_thenCorrect, whenUpdated_thenCorrect, and whenDeleted_thenNotFound perform Create, Read, Update, and Delete operations respectively.

6. Assertions such as assertNotNull, assertEquals, and assertNull are used to verify the behavior of the repository operations.

7. After running the tests, the in-memory database is cleared as each test method is transactional and automatically rolled back, thanks to @DataJpaTest.


Comments