Testing Spring Boot apps
The testing pyramid, from many fast tests to a few slow ones:
- Unit tests: plain JUnit 5 and Mockito, no Spring context. Constructor injection makes these easy.
- Slice tests load a single layer:
@WebMvcTest(controllers with MockMvc),@DataJpaTest(repositories with a test database),@JsonTest. - Integration tests:
@SpringBootTestloads the whole application context.
Testcontainers starts real PostgreSQL, Kafka or Redis in Docker for your tests. With @ServiceConnection (Boot 3.1+), no manual URL wiring is needed.
Replace a bean in the Spring context with a mock using @MockitoBean (Spring 6.2+; it replaces the deprecated @MockBean).
Example
@WebMvcTest(CourseController.class)
class CourseControllerTest {
@Autowired MockMvc mvc;
@MockitoBean CourseService service;
@Test
void returnsCourse() throws Exception {
when(service.bySlug("spring-boot"))
.thenReturn(new CourseDto("Spring Boot", 42, Plan.PRO));
mvc.perform(get("/api/v1/courses/spring-boot"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.title").value("Spring Boot"));
}
}
@SpringBootTest
@Testcontainers
class EnrollmentIT {
@Container
@ServiceConnection
static PostgreSQLContainer<?> db = new PostgreSQLContainer<>("postgres:17");
@Autowired EnrollmentService service;
@Test
void enrollsStudent() { /* real database, real transactions */ }
}Common mistake
Using @SpringBootTest for everything. Loading the full context makes the suite slow; most tests should be unit or slice tests.
Under the hood
Spring caches application contexts between tests that share the same configuration. Every different set of @MockitoBeans or properties creates a new context and slows the suite, so prefer slices and shared base classes, and start the database container once per JVM (a static field). H2 standing in for PostgreSQL hides dialect differences; Testcontainers catches them.
Check yourself
Which annotation tests only JPA repositories?
How this connects
Where this leads
Part of Job-ready backend developer, Microservices and production.
Was this lesson helpful?
Finished reading? Mark it complete to track your progress.