Testing Spring Boot Applications
Spring Boot provides first-class testing support with @SpringBootTest, @WebMvcTest, @DataJpaTest, and Mockito. A solid test suite covers unit tests for services, slice tests for controllers, and integration tests with a real database.
1 Controller Slice Tests (@WebMvcTest)
Java — UserControllerTest.java
@WebMvcTest(UserController.class) // Only loads web layer, not full context
class UserControllerTest {
@Autowired
private MockMvc mockMvc;
@MockBean
private UserService userService;
@Autowired
private ObjectMapper objectMapper;
@Test
void getUser_whenExists_returns200() throws Exception {
UserDto dto = new UserDto(1L, "Balaji", "b@test.com", Role.USER, true);
when(userService.findById(1L)).thenReturn(dto);
mockMvc.perform(get("/api/v1/users/1")
.header("Authorization", "Bearer " + validToken))
.andExpect(status().isOk())
.andExpect(jsonPath("$.name").value("Balaji"))
.andExpect(jsonPath("$.email").value("b@test.com"));
}
@Test
void createUser_withInvalidBody_returns400() throws Exception {
var req = new CreateUserRequest("", "not-an-email", "weak");
mockMvc.perform(post("/api/v1/users")
.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsString(req)))
.andExpect(status().isBadRequest())
.andExpect(jsonPath("$.code").value("VALIDATION_ERROR"))
.andExpect(jsonPath("$.fieldErrors.name").exists())
.andExpect(jsonPath("$.fieldErrors.email").exists());
}
}
2 Repository Tests (@DataJpaTest)
Java — UserRepositoryTest.java
@DataJpaTest // Uses in-memory H2, only loads JPA layer
@AutoConfigureTestDatabase(replace = Replace.NONE) // Use real PostgreSQL
class UserRepositoryTest {
@Autowired
private UserRepository userRepository;
@Autowired
private TestEntityManager em;
@Test
void findByEmail_whenExists_returnsUser() {
User user = new User("Balaji", "b@test.com", "hash", Role.USER);
em.persistAndFlush(user);
Optional<User> found = userRepository.findByEmail("b@test.com");
assertThat(found).isPresent();
assertThat(found.get().getName()).isEqualTo("Balaji");
}
@Test
void existsByEmail_whenNotExists_returnsFalse() {
assertThat(userRepository.existsByEmail("nobody@test.com")).isFalse();
}
}
3 Code Challenge
Challenge: Write a full integration test using
@SpringBootTest(webEnvironment = RANDOM_PORT) and TestRestTemplate that registers a user, logs in to get a JWT, then uses it to call a protected endpoint. Use Testcontainers to spin up a real PostgreSQL container.