spring-boot-test
Test a Spring Boot application
The transactional-test trap — tests can lie about rollback behavior
@Transactional on a test class makes Spring wrap the whole test in a transaction and roll it back after the test finishes — this default exists so tests don't pollute the database, and applies automatically to @DataJpaTest even without writing @Transactional explicitly.
The trap: this same auto-rollback can hide a real production bug. If the code under test is itself supposed to catch a failure and roll back only part of an operation, wrapping the whole test in one outer transaction means the test's assertions run inside a transaction that was always going to roll back anyway — so a test can pass even if the application code's own rollback logic is broken, because the test's outer rollback masks it.
For genuinely verifying a service's own rollback behavior, don't rely on the test's ambient transaction — run the operation via a separate thread/thread pool or an actual HTTP call through MockMvc/WebTestClient (which executes outside the test's transaction), then assert the database state afterward from the test's own connection.
Also note: @SpringBootTest with WebEnvironment.RANDOM_PORT/DEFINED_PORT runs the test client in a separate thread from the server — in this mode, @Transactional on the test does not roll back what the server-side code committed, since they're different connections/threads. Use @Sql scripts or manual cleanup in @AfterEach for this test style instead of relying on @Transactional.
Test pyramid — pick the right layer
- Unit tests (majority of the suite): plain
@ExtendWith(MockitoExtension.class)for service logic, no Spring context. Fastest, use for business rules. - Slice tests:
@WebMvcTestfor controllers (loads only the web layer),@DataJpaTestfor repositories (loads only JPA-related beans). Use these instead of a full context whenever the test only touches one layer. - Integration tests:
@SpringBootTestwith a real database via Testcontainers, for end-to-end verification before deployment. Use sparingly — these are the slowest tests.