Spring Boot: From Basics to Production · Testing Spring Boot Applications

Repository Tests with Testcontainers

Test queries against a real PostgreSQL in Docker.

@DataJpaTest starts only JPA components and wraps each test in a rolled-back transaction. Combine it with Testcontainers and @ServiceConnection so Spring Boot automatically points the datasource at a real PostgreSQL container — no URL wiring. Disable the embedded database replacement, and let Flyway apply your real migrations.

@DataJpaTest
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
@Testcontainers
class OrderRepositoryTest {

    @Container
    @ServiceConnection
    static PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>("postgres:17-alpine");

    @Autowired OrderRepository orders;
    @Autowired TestEntityManager em;

    @Test
    void summariesReturnsOnlyRequestedStatuses() {
        var customer = em.persist(new Customer("[email protected]"));
        em.persist(Order.paid(customer, 1_000));
        em.persist(Order.cancelled(customer, 500));

        var page = orders.summaries(customer.getId(), List.of(OrderStatus.PAID), PageRequest.of(0, 10));

        assertThat(page.getContent()).extracting(OrderSummary::status).containsOnly(OrderStatus.PAID);
    }
}

Common pitfalls

  • Testing PostgreSQL queries on H2 (dialect differences hide bugs).
  • Starting a new container per test class without reuse (slow).
  • Relying on data from other tests.

Key points

  • @DataJpaTest slice
  • Testcontainers + @ServiceConnection
  • Real migrations, real engine

Further reading: Spring Boot: Testcontainers

Practice questions

What does @ServiceConnection do?

Answer

It tells Spring Boot to derive connection details (URL, username, password) from the Testcontainers container automatically, replacing manual @DynamicPropertySource wiring.

Why not use H2 for repository tests of a PostgreSQL app?

Answer

H2 differs in SQL dialect, types, locking and functions, so tests can pass while production queries fail (or vice versa).

Open in the app to mark lessons complete, take notes and track your progress.