Bird
Raised Fist0
JUnittesting~15 mins

@DataJpaTest for repository testing in JUnit - Build an Automation Script

Choose your learning style10 modes available
Verify saving and retrieving an entity using @DataJpaTest
Preconditions (3)
Step 1: Create a new User object with name 'Alice'
Step 2: Save the User object using UserRepository
Step 3: Retrieve the User by its id using UserRepository
Step 4: Verify the retrieved User is not null
Step 5: Verify the retrieved User's name is 'Alice'
✅ Expected Result: The User entity is saved and retrieved correctly with the name 'Alice'
Automation Requirements - JUnit 5 with Spring Boot Test
Assertions Needed:
Assert that the retrieved User is not null
Assert that the retrieved User's name equals 'Alice'
Best Practices:
Use @DataJpaTest annotation for repository testing
Use @Autowired to inject the repository
Use @Test annotation for test methods
Use assertThat from AssertJ for readable assertions
Use @Transactional rollback behavior provided by @DataJpaTest
Automated Solution
JUnit
package com.example.demo;

import static org.assertj.core.api.Assertions.assertThat;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;

import java.util.Optional;

@DataJpaTest
class UserRepositoryTest {

    @Autowired
    private UserRepository userRepository;

    @Test
    void testSaveAndFindUser() {
        // Create a new User
        User user = new User();
        user.setName("Alice");

        // Save the User
        User savedUser = userRepository.save(user);

        // Retrieve the User by id
        Optional<User> retrievedUserOpt = userRepository.findById(savedUser.getId());

        // Verify the User is present
        assertThat(retrievedUserOpt).isPresent();

        User retrievedUser = retrievedUserOpt.get();

        // Verify the name is 'Alice'
        assertThat(retrievedUser.getName()).isEqualTo("Alice");
    }
}

// Entity class
package com.example.demo;

import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;

@Entity
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

// Repository interface
package com.example.demo;

import org.springframework.data.jpa.repository.JpaRepository;

public interface UserRepository extends JpaRepository<User, Long> {
}

This test class uses @DataJpaTest to load only the JPA components and an in-memory database for fast testing.

The UserRepository is injected with @Autowired. The test method testSaveAndFindUser creates a new User entity, saves it, and then retrieves it by its generated ID.

Assertions check that the retrieved user exists and that its name matches the expected value 'Alice'.

The entity class User uses JPA annotations for ID generation and mapping.

This setup ensures the repository works correctly with the database layer without loading the full application context.

Common Mistakes - 4 Pitfalls
Not using @DataJpaTest and loading the full Spring context
Not checking if Optional is present before accessing the entity
{'mistake': "Hardcoding IDs instead of using the saved entity's generated ID", 'why_bad': 'IDs are generated by the database and may not be predictable.', 'correct_approach': 'Use the ID returned from the save() method to retrieve the entity.'}
Not using assertions from AssertJ or JUnit and relying on print statements
Bonus Challenge

Now add data-driven testing with 3 different User names to verify saving and retrieving works for each.

Show Hint

Practice

(1/5)
1. What is the primary purpose of using @DataJpaTest in Spring Boot testing?
easy
A. To perform integration testing with external APIs
B. To test the entire Spring Boot application including web layers
C. To test only the service layer without database access
D. To test only the JPA repositories with an in-memory database setup

Solution

  1. Step 1: Understand the role of @DataJpaTest

    @DataJpaTest is designed to test JPA repositories specifically, setting up only database-related components.
  2. Step 2: Recognize the default database setup

    It uses an in-memory database by default to keep tests fast and isolated.
  3. Final Answer:

    To test only the JPA repositories with an in-memory database setup -> Option D
  4. Quick Check:

    @DataJpaTest = repository testing with in-memory DB [OK]
Hint: Remember @DataJpaTest focuses on repositories only [OK]
Common Mistakes:
  • Thinking it tests the whole application
  • Confusing it with @SpringBootTest
  • Assuming it tests service or controller layers
2. Which annotation is NOT typically used together with @DataJpaTest for repository testing?
easy
A. @AutoConfigureTestDatabase
B. @SpringBootTest
C. @Transactional
D. @MockBean

Solution

  1. Step 1: Identify annotations used with @DataJpaTest

    @DataJpaTest automatically includes @Transactional and often uses @AutoConfigureTestDatabase to control DB setup.
  2. Step 2: Understand @SpringBootTest role

    @SpringBootTest loads the full application context, which is not typical with @DataJpaTest that loads a slice for repositories.
  3. Final Answer:

    @SpringBootTest -> Option B
  4. Quick Check:

    @DataJpaTest excludes full context, so no @SpringBootTest [OK]
Hint: Full app context uses @SpringBootTest, not @DataJpaTest [OK]
Common Mistakes:
  • Using @SpringBootTest with @DataJpaTest unnecessarily
  • Confusing @MockBean usage in repository tests
  • Ignoring transactional rollback behavior
3. Given the following test code snippet using @DataJpaTest:
@DataJpaTest
public class UserRepositoryTest {
  @Autowired
  private UserRepository userRepository;

  @Test
  void testSaveAndFind() {
    User user = new User(null, "Alice");
    userRepository.save(user);
    Optional<User> found = userRepository.findByName("Alice");
    assertTrue(found.isPresent());
  }
}
What will be the test result when executed?
medium
A. Test fails due to missing @Transactional annotation
B. Test fails because the database is not initialized
C. Test passes because the user is saved and found correctly
D. Test fails because userRepository is null

Solution

  1. Step 1: Analyze @DataJpaTest behavior

    @DataJpaTest sets up an in-memory database and configures repositories automatically with transactional rollback.
  2. Step 2: Check test logic

    The test saves a user and then finds it by name. Since the repository is autowired and database is in-memory, the user will be found.
  3. Final Answer:

    Test passes because the user is saved and found correctly -> Option C
  4. Quick Check:

    Save + find with @DataJpaTest = pass [OK]
Hint: In-memory DB + @DataJpaTest means save/find works in tests [OK]
Common Mistakes:
  • Assuming database is empty or uninitialized
  • Forgetting @DataJpaTest provides @Transactional by default
  • Thinking repository needs manual initialization
4. Consider this test class using @DataJpaTest:
@DataJpaTest
public class ProductRepositoryTest {
  @Autowired
  private ProductRepository productRepository;

  @Test
  void testFindById() {
    Product product = new Product(1L, "Book");
    productRepository.save(product);
    Product found = productRepository.findById(1L).orElse(null);
    assertNotNull(found);
  }
}
The test fails with an AssertionError on assertNotNull(found). What is the most likely cause?
medium
A. The Product entity is missing an @Entity annotation
B. The productRepository is not autowired correctly
C. The save method does not persist the entity in @DataJpaTest
D. The test method is missing @Transactional annotation

Solution

  1. Step 1: Check entity configuration

    If the Product class lacks @Entity, JPA won't map it, so save won't persist anything.
  2. Step 2: Understand repository autowiring and transactions

    @DataJpaTest autowires repositories and runs tests in transactions by default, so these are unlikely causes.
  3. Final Answer:

    The Product entity is missing an @Entity annotation -> Option A
  4. Quick Check:

    Missing @Entity means no persistence [OK]
Hint: Always check @Entity on classes for JPA persistence [OK]
Common Mistakes:
  • Assuming @Transactional is missing in @DataJpaTest
  • Thinking save() doesn't work in tests
  • Ignoring entity annotations
5. You want to test a custom query method in your repository using @DataJpaTest. The method returns a list of users with age greater than a given value. Which of the following is the best practice to ensure your test is reliable and isolated?
hard
A. Use @DataJpaTest with an in-memory database and insert test users before querying
B. Use @SpringBootTest and connect to the production database for real data
C. Mock the repository method using @MockBean and verify the return values
D. Write the test without inserting data, assuming the database has users

Solution

  1. Step 1: Understand test isolation with @DataJpaTest

    @DataJpaTest uses an in-memory database that starts empty for each test, so you must insert test data.
  2. Step 2: Avoid external dependencies and mocks for repository tests

    Using production DB or mocks defeats the purpose of repository testing with real JPA behavior.
  3. Final Answer:

    Use @DataJpaTest with an in-memory database and insert test users before querying -> Option A
  4. Quick Check:

    Insert test data in @DataJpaTest for reliable queries [OK]
Hint: Always insert test data in @DataJpaTest for accurate results [OK]
Common Mistakes:
  • Connecting to production DB in tests
  • Relying on existing data without setup
  • Mocking repository methods instead of real queries
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard