java 50 lines · 8 steps

Testing a JPA repository against real Postgres in Spring

A @DataJpaTest slice runs repository queries against a throwaway Postgres container instead of an in-memory database.

Explained by highlit
1@DataJpaTest
2@Testcontainers
3@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
4class OrderRepositoryIT {
5 
6 @Container
7 static PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>("postgres:16-alpine")
8 .withDatabaseName("shop")
9 .withUsername("shop")
10 .withPassword("secret");
11 
12 @DynamicPropertySource
13 static void datasourceProps(DynamicPropertyRegistry registry) {
14 registry.add("spring.datasource.url", postgres::getJdbcUrl);
15 registry.add("spring.datasource.username", postgres::getUsername);
16 registry.add("spring.datasource.password", postgres::getPassword);
17 registry.add("spring.jpa.hibernate.ddl-auto", () -> "create-drop");
18 }
19 
20 @Autowired
21 private TestEntityManager em;
22 
23 @Autowired
24 private OrderRepository orders;
25 
26 private Customer alice;
27 
28 @BeforeEach
29 void seed() {
30 alice = em.persist(new Customer("alice@example.com", "Alice"));
31 Customer bob = em.persist(new Customer("bob@example.com", "Bob"));
32 
33 em.persist(new Order(alice, new BigDecimal("49.90"), OrderStatus.SHIPPED));
34 em.persist(new Order(alice, new BigDecimal("12.00"), OrderStatus.PENDING));
35 em.persist(new Order(bob, new BigDecimal("99.99"), OrderStatus.SHIPPED));
36 
37 em.flush();
38 em.clear();
39 }
40 
41 @Test
42 void findsPendingOrdersForCustomer() {
43 List<Order> pending = orders.findByCustomerAndStatus(alice, OrderStatus.PENDING);
44 
45 assertThat(pending).hasSize(1)
46 .first()
47 .extracting(Order::getTotal)
48 .isEqualTo(new BigDecimal("12.00"));
49 }
50}
01 / 01
STEP 01

Walkthrough

Space play step click any line
Three takeaways
  1. 1Testing repositories against the real database engine catches dialect-specific bugs an in-memory substitute would hide.
  2. 2@DynamicPropertySource wires runtime container details into Spring config before the context starts.
  3. 3Flushing and clearing the persistence context forces queries to hit the database rather than the entity cache.

Related explainers

Share this explainer

Here's the card — post it anywhere.

Testing a JPA repository against real Postgres in Spring — share card
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code