Gymterview
middle

Как тестировать репозитории с помощью DataJpaTest?

@DataJpaTest — срезовая аннотация для тестирования JPA-репозиториев. Она загружает только компоненты, связанные с JPA (@Entity, @Repository, EntityManager), автоматически настраивает встроенную базу данных и применяет @Transactional с откатом после каждого теста.

Что делает DataJpaTest

  • Загружает только JPA-компоненты
  • Автоматически настраивает встроенную БД (H2, HSQLDB или Derby)
  • Применяет @Transactional с откатом
  • Не загружает @Service, @Controller и другие бины
Пример теста репозитория
@DataJpaTest
class UserRepositoryTest {

    @Autowired
    private UserRepository userRepository;

    @Autowired
    private TestEntityManager entityManager;

    @Test
    void shouldFindUserByEmail() {
        User user = new User("Иван", "ivan@example.com");
        entityManager.persistAndFlush(user);

        Optional<User> found = userRepository.findByEmail("ivan@example.com");

        assertTrue(found.isPresent());
        assertEquals("Иван", found.get().getName());
    }

    @Test
    void shouldReturnEmptyWhenEmailNotFound() {
        Optional<User> found = userRepository.findByEmail("unknown@example.com");
        assertTrue(found.isEmpty());
    }

    @Test
    void shouldFindUsersByNameContaining() {
        entityManager.persist(new User("Иванов Иван", "ivan@example.com"));
        entityManager.persist(new User("Иванова Мария", "maria@example.com"));
        entityManager.persist(new User("Петров Пётр", "petr@example.com"));
        entityManager.flush();

        List<User> result = userRepository.findByNameContaining("Иванов");

        assertEquals(2, result.size());
    }

    @Test
    void shouldSaveAndRetrieveUser() {
        User user = new User("Тест", "test@example.com");
        User saved = userRepository.save(user);

        entityManager.clear(); // очищаем кэш первого уровня

        User found = userRepository.findById(saved.getId()).orElseThrow();
        assertEquals("Тест", found.getName());
    }
}

Использование реальной БД вместо встроенной

Пример
@DataJpaTest
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
class UserRepositoryRealDbTest {
    // Использует реальную БД из application.properties/yml
}

Зависимость H2 для тестов:

Пример
<dependency>
    <groupId>com.h2database</groupId>
    <artifactId>h2</artifactId>
    <scope>test</scope>
</dependency>

На собеседовании: важно объяснить, что @DataJpaTest — это slice-тест, который поднимает только JPA-слой, а не весь контекст. Частая ошибка — не упомянуть автоматический rollback и TestEntityManager.