Daten-Slice-Tests mit @DataJpaTest
Repositories und Abfragen gegen eine echte (Test-)Datenbank testen, ohne den Rest der Anwendung.
Deutsche Übersetzung in Arbeit
Diese Lektion ist noch nicht ins Deutsche übersetzt und wird daher auf Englisch angezeigt. Der Rest der Seite ist vollständig lokalisiert.
Auf dieser Seite
Your repositories carry real logic - derived queries, JPQL, JOIN FETCH. A mock can't
tell you whether findByAuthorIgnoreCaseOrderByTitleAsc actually returns the right rows
in the right order; only a database can. @DataJpaTest starts just the JPA layer
against a test database so you can verify queries for real, fast.
The slice
@DataJpaTest configures JPA, Hibernate, and your repositories - and nothing else
(no web layer, no services, no security). It gives each test a fresh, isolated database
and rolls back after every test, so tests never pollute each other.
@DataJpaTest
class BookRepositoryTest {
@Autowired BookRepository repository;
@Test
void findsBooksByAuthorSortedByTitle() {
repository.save(new Book("978-1", "Zebra", "Bloch", 1));
repository.save(new Book("978-2", "Apple", "Bloch", 1));
repository.save(new Book("978-3", "Other", "Gosling", 1));
var books = repository.findByAuthorIgnoreCaseOrderByTitleAsc("bloch");
assertThat(books).extracting(Book::getTitle).containsExactly("Apple", "Zebra");
}
}You saved real rows and ran a real query - the assertion proves the derived method's
WHERE, ORDER BY, and case-insensitivity all work.
Each test starts clean and rolls back
@DataJpaTest wraps each test in a transaction that's rolled back at the end, so tests are isolated and repeatable - you never have to clean up data between them.
H2 now, the real engine later
By default @DataJpaTest uses an embedded database (H2). That's fast and fine for
straightforward queries, but H2 isn't PostgreSQL - a native query or a database-specific
feature can pass on H2 and fail in production. That gap is exactly what Testcontainers
(next lesson) closes, by pointing the same slice at a real PostgreSQL container.
You can't verify a building's plumbing by reading the blueprint - you have to turn the
water on and watch it flow through the actual pipes. Mocking a repository tests the
blueprint; @DataJpaTest turns the water on. It runs your queries through a real JPA
provider and a real (if lightweight) database, so you find leaks the diagram can't show.
BookVault's LoanRepository.findActiveByMember uses a JPQL JOIN FETCH to load each
loan's book and member. Why can a plain unit test with a mocked repository never verify
this method works, and what would a @DataJpaTest prove that a mock cannot?
What does @DataJpaTest load and test?
Key takeaways
- @DataJpaTest starts only the JPA layer and repositories against a test database - no web, service, or security.
- It runs real queries against real rows, so it verifies derived methods, JPQL, ordering, and mappings a mock never could.
- Each test is wrapped in a transaction and rolled back, keeping tests isolated and repeatable.
- By default it uses embedded H2; database-specific behavior may differ from production.
- Point the same slice at a real engine with Testcontainers to close the H2-vs-production gap.