Home/Learn/Spring Boot/@DataJpaTest

@DataJpaTest

Intermediate
Testing

Loads only the JPA layer, auto-configures an in-memory DB, and rolls back each test; ideal for testing repository query correctness in isolation.

Overview

@DataJpaTest is a Spring Boot test slice for the JPA layer: it loads entities, repositories, @Converters, and Hibernate configuration but not controllers, services, or @Component beans. By default it replaces the configured DataSource with an embedded H2 in-memory database and wraps each test in a transaction that rolls back after the test, leaving no state behind. This makes tests fast and deterministic. For tests that need a real database engine (to test MySQL-specific features, window functions, or migration correctness), replace H2 with Testcontainers by adding @AutoConfigureTestDatabase(replace = NONE) and providing a real DataSource.

Basic @DataJpaTest repository test

Test custom @Query methods and derived queries against an H2 in-memory database. TestEntityManager is injected for setting up test data without going through repositories.

Java — @DataJpaTest with TestEntityManager
@DataJpaTest   // loads only JPA slice; H2 replaces configured DB
class OrderRepositoryTest {

    @Autowired
    private TestEntityManager em;

    @Autowired
    private OrderRepository orderRepository;

    @Test
    void findByStatus_returnsPendingOrders() {
        // Arrange: persist test data via TestEntityManager
        Customer customer = em.persist(new Customer("john@example.com"));
        em.persist(new Order(customer, "PENDING", new BigDecimal("50.00")));
        em.persist(new Order(customer, "SHIPPED", new BigDecimal("30.00")));
        em.persist(new Order(customer, "PENDING", new BigDecimal("20.00")));
        em.flush();

        // Act
        List<Order> result = orderRepository.findByStatus("PENDING");

        // Assert
        assertThat(result).hasSize(2)
            .extracting(Order::getStatus)
            .containsOnly("PENDING");
    }

    @Test
    void findTopSpenders_returnsCustomersSortedByRevenue() {
        // Test a native query with aggregation
        // ...
        List<CustomerRevenue> top = orderRepository.findTopSpenders(
            PageRequest.of(0, 5));
        assertThat(top).isSortedAccordingTo(
            Comparator.comparing(CustomerRevenue::getTotalRevenue).reversed());
    }
}

@DataJpaTest with Testcontainers (real MySQL)

Replace H2 with a real MySQL container when tests need database-specific behaviour: window functions, JSON functions, or Flyway migration correctness.

Java — @DataJpaTest + Testcontainers for real MySQL
@DataJpaTest
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
@Testcontainers
class OrderRepositoryMySQLTest {

    @Container
    static MySQLContainer<?> mysql = new MySQLContainer<>("mysql:8.3")
        .withDatabaseName("testdb")
        .withUsername("test")
        .withPassword("test");

    @DynamicPropertySource
    static void configureProperties(DynamicPropertyRegistry registry) {
        registry.add("spring.datasource.url",    mysql::getJdbcUrl);
        registry.add("spring.datasource.username", mysql::getUsername);
        registry.add("spring.datasource.password", mysql::getPassword);
        registry.add("spring.jpa.hibernate.ddl-auto", () -> "create-drop");
        // Or use Flyway: spring.flyway.enabled=true
    }

    @Autowired
    private OrderRepository orderRepository;

    @Test
    void windowFunctionQuery_ranksOrdersCorrectly() {
        // This test requires MySQL window functions — fails on H2
        List<OrderRank> ranked = orderRepository.rankOrdersByValue();
        assertThat(ranked.get(0).getRank()).isEqualTo(1);
    }
}

Testing auditing and custom converters

@DataJpaTest includes @Converters and auditing infrastructure. Test that @CreatedDate, @LastModifiedDate, and custom AttributeConverters work correctly.

Java — testing JPA auditing in @DataJpaTest
@DataJpaTest
@Import(JpaConfig.class)  // import @EnableJpaAuditing config
class AuditingTest {

    @Autowired
    private TestEntityManager em;

    @Autowired
    private OrderRepository orderRepository;

    @Test
    void createdAt_isSetOnPersist() {
        Order order = new Order("cust-1", "PENDING", BigDecimal.TEN);
        Order saved = orderRepository.saveAndFlush(order);

        assertThat(saved.getCreatedAt()).isNotNull();
        assertThat(saved.getUpdatedAt()).isNotNull();
        assertThat(saved.getCreatedAt()).isBeforeOrEqualTo(saved.getUpdatedAt());
    }

    @Test
    void updatedAt_changesOnUpdate() throws InterruptedException {
        Order order = orderRepository.saveAndFlush(
            new Order("cust-1", "PENDING", BigDecimal.TEN));
        LocalDateTime original = order.getUpdatedAt();
        Thread.sleep(10);

        order.setStatus("CONFIRMED");
        Order updated = orderRepository.saveAndFlush(order);

        assertThat(updated.getUpdatedAt()).isAfter(original);
    }
}

Key Points to Remember

  • 1@DataJpaTest loads JPA layer only — no controllers, no services, no @Component beans.
  • 2Each test runs in a transaction that rolls back automatically — no teardown required.
  • 3H2 in-memory database is used by default; add @AutoConfigureTestDatabase(replace=NONE) to use a real DB.
  • 4TestEntityManager wraps EntityManager with helpers like persist(), flush(), find() useful for test setup.
  • 5Use Testcontainers for MySQL-specific features (JSON functions, window functions, Flyway migrations).
  • 6Import @EnableJpaAuditing configuration explicitly if it is not auto-applied in the slice.

Interview Questions

Sign in to ask Aria
1

What does @DataJpaTest load and what does it exclude?

EasyAmazon
2

Why might a test pass with H2 but fail with MySQL in a @DataJpaTest?

MediumNetflix
3

How do you use Testcontainers with @DataJpaTest to test against a real database?

MediumGoogle
4

What is the difference between TestEntityManager and a regular repository in @DataJpaTest?

MediumShopify
5

How do you test that a custom @Query method returns the correct pagination metadata?

MediumZalando

Ask Aria about @DataJpaTest

Your personal AI tutor — ask anything about this concept

Revision Status

Personal Notes

Sign in to save personal notes for this topic.

Discussion

Sign in to join the discussion.

Loading discussion…