Skip to main content

8.1 Testing Strategy & Test Slices

← Back to Chapter 8: Testing, Deployment & Production-Ready Spring Boot

A balanced testing pyramid combines fast unit tests, focused test slices, and end-to-end integration tests.


1. The Spring Boot Testing Pyramid​

/ \
/ \ End-to-End (@SpringBootTest)
/ \ - Slowest, spins up full ApplicationContext
/-------\
/ \ Test Slices (@WebMvcTest, @DataJpaTest)
/ \ - Medium speed, loads only 1 architectural tier
/-------------\
/ \ Pure Unit Tests (JUnit 5 + Mockito)
/ \- Fastest (milliseconds), NO Spring context
/-------------------\

2. Spring Test Slices​

Instead of bootstrapping hundreds of services and repositories, Test Slices instantiate only components relevant to the layer under test:

Test Slice AnnotationWhat It LoadsTypical Collaborators Mocked
@WebMvcTest(UserController.class)@Controller, @RestControllerAdvice, Filter, MockMvcService dependencies (@MockBean)
@DataJpaTest@Entity, JpaRepository, embedded DB, SQL loggingWeb layer, Services (completely excluded)
@JsonTestJackson serializers and deserializersValidates JSON formatting and dates

Controller Slice Test with MockMvc:​

@WebMvcTest(UserController.class)
class UserControllerTest {

@Autowired
private MockMvc mockMvc;

@MockBean
private UserService userService;

@Test
void shouldReturnUserWhenFound() throws Exception {
UserDTO mockUser = new UserDTO(1L, "Sarwvidya", "sarvy@codewithsarvy.dev");
Mockito.when(userService.findById(1L)).thenReturn(mockUser);

mockMvc.perform(get("/api/v1/users/1")
.accept(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(jsonPath("$.id").value(1))
.andExpect(jsonPath("$.fullName").value("Sarwvidya"))
.andExpect(jsonPath("$.email").value("sarvy@codewithsarvy.dev"));
}
}

3. Full Integration Testing with @SpringBootTest​

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@AutoConfigureMockMvc
class UserIntegrationTest {

@Autowired
private MockMvc mockMvc;

@Autowired
private UserRepository userRepository;

@Test
void endToEndUserRegistration() throws Exception {
String payload = """
{
"email": "test@codewithsarvy.dev",
"fullName": "Test User",
"password": "Password123!"
}
""";

mockMvc.perform(post("/api/v1/users")
.contentType(MediaType.APPLICATION_JSON)
.content(payload))
.andExpect(status().isCreated());

assertTrue(userRepository.findByEmail("test@codewithsarvy.dev").isPresent());
}
}