๐งช Spring Boot Integration Tests & Database Lifecycle
This document explains how Spring Boot manages the database lifecycle during integration tests โ specifically when the database is created, when it's dropped, and how isolation is achieved.
> ๐ข๏ธ Database Creation and Dropping
>> When is the database created?
When using an in-memory database like H2 and spring.jpa.hibernate.ddl-auto=create-drop:
- โ The database schema is created once, when the application context is first started.
- This usually happens once per test class, if you're using
@SpringBootTest. - The same context (and DB schema) is reused across test methods in the same class.
- โ The database is not recreated before each test method.
>> When is the database dropped?
- With
ddl-auto=create-drop, the schema is dropped automatically when the Spring context shuts down, i.e.: - After the test class finishes (if context was specific to that class)
- Or at the end of the full test suite (if context was reused)
> โป๏ธ Transactional Rollback and Isolation
>> What does @Transactional do?
When a test class or test method is annotated with @Transactional:
- Each test method runs in its own transaction
- After the test method completes, the transaction is rolled back
- This leaves the database in a clean state between tests โ without recreating the schema
>> Example
@SpringBootTest
@Transactional
class MyIntegrationTest {
@Autowired
UserRepository userRepository;
@Test
void testCreateUser() {
userRepository.save(new User("Alice"));
// Rolled back after the test method finishes
}
}
> ๐ Controlling DB and Context Scope
| Situation | Context Reused? | DB Recreated? | Notes |
|---|---|---|---|
| Multiple tests in same class | โ Yes | โ No | Same context, same schema |
| Multiple test classes (default) | โ Yes | โ No | Spring optimizes by reusing context |
With @DirtiesContext |
โ No | โ Yes | Forces full context + DB reset |
With @Transactional |
โ Yes | โ No | Rollback used instead of full reset |
> ๐ Best Practices for Integration Tests
โ
Use @Transactional to ensure clean state without heavy DB recreation
โ
Use ddl-auto=create-drop for in-memory DBs (e.g. H2) to keep schema fresh
โ
Use @DirtiesContext only when you need full context isolation
โ
Use fixture loaders (e.g. JSON or SQL) to control test data explicitly
โ ๏ธ Avoid ddl-auto=update in tests โ unpredictable and risky
โ ๏ธ Avoid mixing stateful and stateless test strategies in the same class
> โ๏ธ Common Configuration Example
spring:
datasource:
url: jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1
driver-class-name: org.h2.Driver
jpa:
hibernate:
ddl-auto: create-drop
sql:
init:
mode: embedded
๐ Summary
- Spring Boot creates the DB once per context, usually once per test class.
- Schema is created at context startup, dropped at context shutdown.
- Use
@Transactionalfor method-level isolation. - Use
@DirtiesContextif you need class-level isolation with fresh schema.