DataJpaTest Basics
A Slice Test for JPA
@DataJpaTest starts only the JPA part of Spring Boot: entities, repositories, the EntityManager, Flyway/Liquibase and a TestEntityManager. No controllers, no services. Each test runs in a transaction that is rolled back at the end, so tests do not affect each other.
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.boot.test.autoconfigure.orm.jpa.TestEntityManager;
import static org.assertj.core.api.Assertions.assertThat;
@DataJpaTest
class ProductRepositoryTest {
@Autowired TestEntityManager tem;
@Autowired ProductRepository products;
@Test
void findsInStockProductsOfACategory() {
Category mobiles = tem.persist(new Category("Mobiles"));
tem.persist(new Product("Redmi Note 13", new BigDecimal("15999"), 12, mobiles));
tem.persist(new Product("Old Model", new BigDecimal("4999"), 0, mobiles));
tem.flush();
tem.clear(); // make the repository really hit the database
List<Product> result = products.findByCategoryNameAndStockGreaterThan("Mobiles", 0);
assertThat(result).extracting(Product::getName).containsExactly("Redmi Note 13");
}
}Tip: Always flush() and clear() after setting up data. Otherwise the repository may return objects straight from the first-level cache and your SQL is never tested.
The Embedded Database Problem
By default @DataJpaTest replaces your DataSource with an in-memory H2 database. H2 is fast, but it is not MySQL or PostgreSQL: native queries, JSON columns, SKIP LOCKED, partial indexes and many functions behave differently or fail. Tests pass, production breaks. The fix is to test against the real database engine with Testcontainers.