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.